C# 检查一个数组是否是另一个数组的子集

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/332973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:34:24  来源:igfitidea点击:

Check whether an array is a subset of another

c#listlinqsubset

提问by Graviton

Any idea on how to check whether that list is a subset of another?

关于如何检查该列表是否是另一个列表的子集的任何想法?

Specifically, I have

具体来说,我有

List<double> t1 = new List<double> { 1, 3, 5 };
List<double> t2 = new List<double> { 1, 5 };

How to check that t2 is a subset of t1, using LINQ?

如何使用 LINQ 检查 t2 是否是 t1 的子集?

采纳答案by Cameron MacFarland

bool isSubset = !t2.Except(t1).Any();

回答by JaredPar

Try this

尝试这个

static bool IsSubSet<A>(A[] set, A[] toCheck) {
  return set.Length == (toCheck.Intersect(set)).Count();
}

The idea here is that Intersect will only return the values that are in both Arrays. At this point if the length of the resulting set is the same as the original set, then all elements in "set" are also in "check" and therefore "set" is a subset of "toCheck"

这里的想法是 Intersect 将只返回两个数组中的值。此时如果结果集的长度与原始集的长度相同,则“set”中的所有元素也在“check”中,因此“set”是“toCheck”的子集

Note: My solution does not work if "set" has duplicates. I'm not changing it because I don't want to steal other people's votes.

注意:如果“set”有重复项,我的解决方案将不起作用。我不会改变它,因为我不想窃取其他人的选票。

Hint: I voted for Cameron's answer.

提示:我投票支持卡梅伦的答案。

回答by tvanfosson

Use HashSet instead of List if working with sets. Then you can simply use IsSubsetOf()

如果使用集合,请使用 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);

Sorry that it doesn't use LINQ. :-(

抱歉,它不使用 LINQ。:-(

If you need to use lists, then @Jared's solution works with the caveat that you will need to remove any repeated elements that exist.

如果您需要使用列表,那么@Jared 的解决方案适用于需要删除任何存在的重复元素的警告。

回答by Neil

@Cameron's solution as an extension method:

@Cameron 的解决方案作为扩展方法:

public static bool IsSubsetOf<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    return !a.Except(b).Any();
}

Usage:

用法:

bool isSubset = t2.IsSubsetOf(t1);

(This is similar, but not quite the same as the one posted on @Michael's blog)

(这很相似,但与@Michael 博客上发布的不完全相同)

回答by Géza

If you are unit-testingyou can also utilize the CollectionAssert.IsSubsetOfmethod :

如果您正在进行单元测试,您还可以使用CollectionAssert.IsSubsetOf方法:

CollectionAssert.IsSubsetOf(subset, superset);

In the above case this would mean:

在上述情况下,这意味着:

CollectionAssert.IsSubsetOf(t2, t1);

回答by user2325458

This is a significantly more efficient solution than the others posted here, especially the top solution:

这是一个比这里发布的其他解决方案更有效的解决方案,尤其是顶级解决方案:

bool isSubset = t2.All(elem => t1.Contains(elem));

If you can find a single element in t2 that isn't in t1, then you know that t2 is not a subset of t1. The advantage of this method is that it is done all in-place, without allocating additional space, unlike the solutions using .Except or .Intersect. Furthermore, this solution is able to break as soon as it finds a single element that violates the subset condition, while the others continue searching. Below is the optimal long form of the solution, which is only marginally faster in my tests than the above shorthand solution.

如果您可以在 t2 中找到不在 t1 中的单个元素,那么您就知道 t2 不是 t1 的子集。与使用 .Except 或 .Intersect 的解决方案不同,这种方法的优点是它全部就地完成,无需分配额外的空间。此外,该解决方案能够在找到违反子集条件的单个元素时立即中断,而其他元素则继续搜索。以下是解决方案的最佳长格式,在我的测试中,它仅比上述速记解决方案快一点。

bool isSubset = true;
foreach (var element in t2) {
    if (!t1.Contains(element)) {
        isSubset = false;
        break;
    }
}

I did some rudimentary performance analysis of all the solutions, and the results are drastic. These two solutions are about 100x faster than the .Except() and .Intersect() solutions, and use no additional memory.

我对所有解决方案进行了一些基本的性能分析,结果非常惊人。这两个解决方案比 .Except() 和 .Intersect() 解决方案快大约 100 倍,并且不使用额外的内存。

回答by sclarke81

Building on the answers from @Cameron and @Neil I wrote an extension method that uses the same terminology as the Enumerable class.

基于@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();
}

回答by Lucifer

Here we check that if there is any element present in the child list(i.e t2) which is not contained by the parent list(i.e t1).If none such exists then the list is subset of the other

在这里,我们检查子列表(即t2)中是否存在父列表(即t1)不包含的任何元素。如果不存在这样的元素,则该列表是另一个列表的子集

eg:

例如:

bool isSubset = !(t2.Any(x => !t1.Contains(x)));