我需要确定两个集合是否包含完全相同的元素。顺序并不重要。
例如,这两个数组应该被认为是相等的:
IEnumerable<int> data = new []{3, 5, 6, 9}; IEnumerable<int> otherData = new []{6, 5, 9, 3}
一个集合不能包含不在另一个集合中的任何元素。
可以使用内置的查询运算符来完成吗?考虑到元素的数量可能从几个到几百个不等,那么最有效的实现方式是什么呢?
这应该会有所帮助:
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;
data.Intersect(otherData);
我建议对两者进行排序,并逐个元素进行比较。
data.OrderBy(x => x).SequenceEqual(otherData.OrderBy(x => x))
我不确定 OrderBy的实现有多快,但如果它是 O (n log n)排序,就像您期望的那样,总算法也是 O (n log n)。
OrderBy
对于某些数据情况,您可以通过使用 OrderBy 的自定义实现来改进这一点,例如,对于 O (n + k) ,使用计数排序,k 为值所在范围的大小。
如果希望将数组视为“ set”,而忽略顺序和重复项,可以使用 HashSet<T>.SetEquals法:
HashSet<T>.SetEquals
var isEqual = new HashSet<int>(first).SetEquals(second);
否则,您最好的选择可能是以相同的方式对两个序列进行排序,并使用 SequenceEqual对它们进行比较。
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);