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

我需要确定两个集合是否包含完全相同的元素。顺序并不重要。

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

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

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

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

38507 次浏览

这应该会有所帮助:

    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
}

如果您可能有副本(或者如果您想要一个对较长列表执行得更好的解决方案) ,我会尝试这样的东西:

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);
}

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

这里有一个简单的方法。注意,这里假设列表没有重复。

bool same = data.Except (otherData).Count() == 0;
  1. 首先,检查长度。如果它们是不同的,设置是不同的。
  2. 你可以做 data.Intersect(otherData);,并检查长度是相同的。
  3. 或者,简单地对集合进行排序,并对它们进行迭代。

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

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

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

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

如果希望将数组视为“ set”,而忽略顺序和重复项,可以使用 HashSet<T>.SetEquals:

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

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

首先检查两个数据集合是否具有相同数量的元素,然后检查一个集合中的所有元素是否在另一个集合中显示

        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));

下面是另一种方法:

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);