C# LINQ:确定两个序列是否包含完全相同的元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1673347/
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-06 19:52:46  来源:igfitidea点击:

LINQ: Determine if two sequences contains exactly the same elements

c#.netlinq

提问by driis

I need to determine whether or not two sets contains exactly the same elements. The ordering does not matter.

我需要确定两个集合是否包含完全相同的元素。顺序无关紧要。

For instance, these two arrays should be considered equal:

例如,这两个数组应该被认为是相等的:

IEnumerable<int> data = new []{3, 5, 6, 9};
IEnumerable<int> otherData = new []{6, 5, 9, 3}

One set cannot contain any elements, that are not in the other.

一个集合不能包含任何不在另一个集合中的元素。

Can this be done using the built-in query operators? And what would be the most efficient way to implement it, considering that the number of elements could range from a few to hundreds?

这可以使用内置查询运算符完成吗?考虑到元素的数量可能从几个到数百个不等,实现它的最有效方法是什么?

采纳答案by Mehrdad Afshari

If you want to treat the arrays as "sets" and ignore order and duplicate items, you can use HashSet<T>.SetEqualsmethod:

如果要将数组视为“集合”并忽略顺序和重复项,可以使用HashSet<T>.SetEquals方法

var isEqual = new HashSet<int>(first).SetEquals(second);

Otherwise, your best bet is probably sorting both sequences in the same way and using SequenceEqualto compare them.

否则,您最好的选择可能是以相同的方式对两个序列进行排序并SequenceEqual用于比较它们。

回答by Blounty

This should help:

这应该有帮助:

    IEnumerable<int> data = new []{ 3,5,6,9 };
    IEnumerable<int> otherData = new[] {6, 5, 9, 3};

    if(data.All(x => otherData.Contains(x)))
    {
        //Code Goes Here
    }

回答by Justin Grant

If you might have duplicates (or if you want a solution which performs better for longer lists), I'd try something like this:

如果您可能有重复项(或者如果您想要一个对更长列表表现更好的解决方案),我会尝试这样的事情:

static bool IsSame<T>(IEnumerable<T> set1, IEnumerable<T> set2)
{
    if (set1 == null && set2 == null)
        return true;
    if (set1 == null || set2 == null)
        return false;

    List<T> list1 = set1.ToList();
    List<T> list2 = set2.ToList();

    if (list1.Count != list2.Count)
        return false;

    list1.Sort();
    list2.Sort();

    return list1.SequenceEqual(list2);
}

UPDATE: oops, you guys are right-- the Except() solution below needs to look both ways before crossing the street. And it has lousy perf for longer lists. Ignore the suggestion below! :-)

更新:哎呀,你们是对的——下面的 except() 解决方案需要在过马路之前看两边。对于较长的列表,它的性能很差。忽略下面的建议!:-)

Here's one easy way to do it. Note that this assumes the lists have no duplicates.

这是一种简单的方法。请注意,这假设列表没有重复项。

bool same = data.Except (otherData).Count() == 0;

回答by Kobi

  1. First, check the length. If they are different, the sets are different.
  2. you can do data.Intersect(otherData);, and check the length is identical.
  3. OR, simplt sort the sets, and iterate through them.
  1. 首先,检查长度。如果它们不同,则集合不同。
  2. 你可以做data.Intersect(otherData);,并检查长度是否相同。
  3. 或者,对集合进行简单排序,然后遍历它们。

回答by Joren

I suggest sorting both, and doing an element-by-element comparison.

我建议对两者进行排序,并进行逐个元素的比较。

data.OrderBy(x => x).SequenceEqual(otherData.OrderBy(x => x))

I'm not sure how fast the implementation of OrderByis, but if it's a O(n log n) sort like you'd expect the total algorithm is O(n log n) as well.

我不确定实现的速度有多快OrderBy,但是如果它是 O(n log n) 排序,就像您期望的那样,总算法也是 O(n log n)。

For some cases of data, you can improve on this by using a custom implementation of OrderBy that for example uses a counting sort, for O(n+k), with k the size of the range wherein the values lie.

对于某些数据情况,您可以通过使用 OrderBy 的自定义实现对此进行改进,例如使用计数排序,对于 O(n+k),k 是值所在范围的大小。

回答by nunoalmeida

First check if both data collections have the same number of elements and the check if all the elements in one collection are presented in the other

首先检查两个数据集合是否具有相同数量的元素,并检查一个集合中的所有元素是否出现在另一个集合中

        IEnumerable<int> data = new[] { 3, 5, 6, 9 };
        IEnumerable<int> otherData = new[] { 6, 5, 9, 3 };

        bool equals = data.Count() == otherData.Count() && data.All(x => otherData.Contains(x));

回答by johnny 5

Here is another way to do it:

这是另一种方法:

IEnumerable<int> data = new[] { 3, 5, 6, 9 };
IEnumerable<int> otherData = new[] { 6, 5, 9, 3 };

data = data.OrderBy(d => d);
otherData = otherData.OrderBy(d => d);
data.Zip(otherData, (x, y) => Tuple.Create(x, y)).All(d => d.Item1 == d.Item2);