是否有内置的linq方法,我可以用它来确定两个序列是否包含相同的项目,而不考虑订单?
例如:
{1, 2, 3} == {2, 1, 3}
{1, 2, 3} != {2, 1, 3, 4}
{1, 2, 3} != {1, 2, 4}
你有SequenceEquals,但是我必须先对两个序列进行排序,不是吗?
答案 0 :(得分:37)
有很多方法。假设A和B是IEnumerable。
!A.Except(B).Any() && !B.Except(A).Any()
A.Count() == B.Count() && A.Intersect(B).Count() == B.Count()
etc
答案 1 :(得分:9)
有两个IEnumerables(A和B):
bool equal = (A.Count() == B.Count() && (!A.Except(B).Any() || !B.Except(A).Any()))
我认为这比Except(A).Count更好,因为不会评估整个Excep。只要在“除外”中找到一个元素,它就会停止。使用Count,可以评估整个Except。 除此之外,我们可以避免对这些代价高昂的评估,除非首先检查Count属性。如果计数不相等,那么我们检查Excepts。
答案 2 :(得分:4)
如果您不关心重复项(即您认为{1, 2, 3}
等于{1, 2, 3, 2}
),那么:
new HashSet<int>(A).SetEquals(B)
(或者任何类型的元素类型而不是int
)。
否则:
public static bool SequenceEqualUnordered<T>(IEnumerable<T> first, IEnumerable<T> second)
{
if (first == null)
return second == null; // or throw if that's more appropriate to your use.
if (second == null)
return false; // likewise.
var dict = new Dictionary<T, int>(); // You could provide a IEqualityComparer<T> here if desired.
foreach(T element in first)
{
int count;
dict.TryGetValue(element, out count);
dict[element] = count + 1;
}
foreach(T element in second)
{
int count;
if (!dict.TryGetValue(element, out count))
return false;
else if (--count == 0)
dict.Remove(element);
else
dict[element] = count;
}
return dict.Count == 0;
}
保持第一个序列中每个元素的计数,然后检查第二个序列。你在第二个序列中有一个太多的那一刻你可以返回false,否则如果你在相关词典中没有任何东西它们是相等的,或者如果剩下任何元素则为false。
使用OrderBy()
后跟O(n)比较的两个O(n log n)种类,而不是O(n)操作构建一组计数,并且是O(n检查它。
答案 3 :(得分:3)
尝试使用HashSet类:
var enumA = new[] { 1, 2, 3, 4 };
var enumB = new[] { 4, 3, 1, 2 };
var hashSet = new HashSet<int>(enumA);
hashSet.SymmetricExceptWith(enumB);
Console.WriteLine(hashSet.Count == 0); //true => equal
但是,如果值不同,那只能正常工作。
例如
var enumA = new[] { 1, 1, 1, 2 };
var enumB = new[] { 1, 2, 2, 2 };
也被认为与上述方法“相同”。
答案 4 :(得分:1)
我认为订购序列是实现这一目标的最快方法。
答案 5 :(得分:1)
我这样做是为了将新项目合并到一个没有重复的集合中, 它需要两个集合并返回所有没有重复的项目
List<Campaign> nonMatching = (from n in newCampaigns
where !(from e in Existing select e.Id).Contains<int>(n.Id)
select n).ToList<Campaign>();
现在删除!对于包含语句
List<Campaign> nonMatching = (from n in newCampaigns
where (from e in Existing select e.Id).Contains<int>(n.Id)
select n).ToList<Campaign>();
它将返回重复项
答案 6 :(得分:0)
如果您真的只是在测试是否有重复项,那么leppie的建议应该有效:
if (A.Except(B).Count == 0 && B.Except(A).Count == 0) {...}
但是如果你只需要一个没有重复的IEnumerable:
var result = A.Union(B).Distinct();
答案 7 :(得分:0)
通过示例,您可以将IEnumerable都设置为List类型,然后使用SequenceEqual作为以下示例:
var first = Enumerable.Range(1, 3);
var second = Enumerable.Range(1, 3);
var areTheyEqual = first.ToList().SequenceEqual(second.ToList());
if (areTheyEqual)
{ /* do something... */}
答案 8 :(得分:0)
为了比较两个对象中的数据,我只使用了
A.Except(B).Any() || B.Except(A).Any()