检查数组是否是另一个数组的子集
任何想法如何检查该列表是否是另一个子集?
具体来说,我有
List<double> t1 = new List<double> { 1, 3, 5 }; List<double> t2 = new List<double> { 1, 5 };
如何检查t2是使用LINQ的t1的一个子集?
bool isSubset = !t2.Except(t1).Any();
如果使用集合,使用HashSet而不是List。 那么你可以简单地使用IsSubsetOf()
HashSet<double> t1 = new HashSet<double>{1,3,5}; HashSet<double> t2 = new HashSet<double>{1,5}; bool isSubset = t2.IsSubsetOf(t1);
对不起,它不使用LINQ。 🙁
如果您需要使用列表,那么@ Jared的解决scheme需要注意,您需要删除存在的任何重复元素。
如果你是unit testing,你也可以使用CollectionAssert.IsSubsetOf方法:
CollectionAssert.IsSubsetOf(subset, superset);
在上述情况下,这将意味着:
CollectionAssert.IsSubsetOf(t2, t1);
作为扩展方法@卡梅隆的解决scheme:
public static bool IsSubsetOf<T>(this IEnumerable<T> a, IEnumerable<T> b) { return !a.Except(b).Any(); }
用法:
bool isSubset = t2.IsSubsetOf(t1);
(这与Michael的博客中的发表类似,但不尽相同)
这是比这里发布的其他解决scheme更有效的解决scheme,特别是顶级解决scheme:
bool isSubset = t2.All(elem => t1.Contains(elem));
如果你可以在t2中find一个不在t1中的单个元素,那么你知道t2不是t1的一个子集。 这种方法的优点是它不需要分配额外的空间就可以完成,不像使用.Except或.Intersect的解决scheme。 此外,只要发现违反子集条件的单个元素,此解决scheme就能够中断,而其他解决scheme则继续search。 以下是解决scheme的最佳长forms,在我的testing中速度比上述速记解决scheme稍快。
bool isSubset = true; foreach (var element in t2) { if (!t1.Contains(element)) { isSubset = false; break; } }
我对所有的解决scheme做了一些基本的性能分析,结果非常激烈。 这两个解决scheme比.Except()和.Intersect()解决scheme快大约100倍,并且不需要额外的内存。
尝试这个
static bool IsSubSet<A>(A[] set, A[] toCheck) { return set.Length == (toCheck.Intersect(set)).Count(); }
这里的想法是Intersect将只返回两个数组中的值。 此时如果结果集合的长度与原始集合的长度相同,则“set”中的所有元素也都在“check”中,因此“set”是“toCheck”的子集。
注意:如果“设置”重复,我的解决scheme不起作用。 我不会改变它,因为我不想窃取别人的选票。
提示:我投赞成卡梅伦的答案。
基于@Cameron和@Neil的答案,我写了一个扩展方法,它使用与Enumerable类相同的术语。
/// <summary> /// Determines whether a sequence contains the specified elements by using the default equality comparer. /// </summary> /// <typeparam name="TSource">The type of the elements of source.</typeparam> /// <param name="source">A sequence in which to locate the values.</param> /// <param name="values">The values to locate in the sequence.</param> /// <returns>true if the source sequence contains elements that have the specified values; otherwise, false.</returns> public static bool ContainsAll<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> values) { return !values.Except(source).Any(); }