2014-06-23 101 views
6

我有两个列表如下,我怎么能说他们有相同的元素。顺序并不重要。检查两个列表是否有相同的项目

var list1 = new List<int> {1,2,3}; 
var list2 = new List<int> {2,1,3}; 

我怎么能说这些是平等的?我应该写我自己的方法还是有内置的方法?

+1

我不认为有建于...很好的候选人的扩展方法 – Liath

回答

14

这是什么设置(例如,HashSet<T>)。集合没有定义的顺序,并且SetEquals验证集合和另一个集合是否包含相同的元素。

var set = new HashSet<int>(list1) 
var equals = set.SetEquals(list2); 
+0

任何将这工作,如果我有对象,而不是整数列表? – Vahid

+0

@Vahid是的。 – dcastro

+1

@Vahid:它取决于对象是否覆盖'Equals'(+'GetHashCode')。您也可以将自定义'IEqualityComparer '传递给'HashSet'的构造函数阅读:http://stackoverflow.com/questions/8952003/how-does-hashset-compare-elements-for-equality –

0

什么:

list1.Count == lis2.Count, then list1.Except(list2).Any() 

或可能(但可能不会):

list1.Intersect(list2).Count == list1.Count; 

编辑:Rotem公司是正确的。我误解了这个问题。这将工作。

+3

我认为你的意思是'除外'。 'Instersect'会返回所有元素,如果它们相等,则需要检查'list1.Intersect(list2).Count()== list1.Count;' – Rotem

+0

当list1是list2的一个子集时,这将失败。 –

1

您可以尝试Except

var result = list1.Except(list2).ToList(); 

Except回报:第一,不会出现在第二

+0

为什么'字符串?另外,检查平等的地方在哪里? – Rotem

+0

如果'list1'为空,则返回一个空列表,这并不意味着两者相等。如果list1是list2的子集,它也会失败。除此之外,没有必要创建另一个集合来检查两个列表是否相等。 –

7

这些元素可以使用!Except + Any

bool list1InList2 = !list1.Except(list2).Any(); 

这没有检查,如果这两个具有相同的项目,但是如果list1包含在list2中(忽略重复项)。

如果你想知道,如果list2包含在list1,使用方法:

bool list2InList1 = !list2.Except(list1).Any(); 

所以你如果你想确保两个列表包含相同的项目,以使双方的检查。

如果您还想要考虑到两个列表的大小相同,请预先检查list1.Count==list2.Count。 但是,如果您使用set方法(参见Harald's comment),则此检查无用,但如果以后忽略重复项,则比较计数没有多大意义。

一般HashSet<T>有一些很好的和有效的方法来检查两个序列是否有相同的项目(忽略重复),dcastro already showed之一。


如果你想要一个有效的解决方案,以确定是否两个列表包含相同的项目,相同的计数没有忽略重复忽略顺序(以其它方式使用SequenceEquals):

public static bool SequenceEqualsIgnoreOrder<T>(this IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer = null) 
{ 
    if(list1 is ICollection<T> ilist1 && list2 is ICollection<T> ilist2 && ilist1.Count != ilist2.Count) 
     return false; 

    if (comparer == null) 
     comparer = EqualityComparer<T>.Default; 

    var itemCounts = new Dictionary<T, int>(comparer); 
    foreach (T s in list1) 
    { 
     if (itemCounts.ContainsKey(s)) 
     { 
      itemCounts[s]++; 
     } 
     else 
     { 
      itemCounts.Add(s, 1); 
     } 
    } 
    foreach (T s in list2) 
    { 
     if (itemCounts.ContainsKey(s)) 
     { 
      itemCounts[s]--; 
     } 
     else 
     { 
      return false; 
     } 
    } 
    return itemCounts.Values.All(c => c == 0); 
} 

用法:

var list1 = new List<int> { 1, 2, 3, 1 }; 
var list2 = new List<int> { 2, 1, 3, 2 }; 
bool sameItemsIgnoringOrder = list1.SequenceEqualsIgnoreOrder(list2); 
// false because same count and same items but 1 appaears twice in list1 but once in list2 

如果订单事项,并重复算过,使用:

bool sameItemsSameOrder = list1.SequenceEqual(list2); 
+2

+1最好的方法。 – Rotem

+0

@Rotem我不知道这是否比'dcastro'建议的方法更快? – Vahid

+0

感谢蒂姆,你的意思是'dcastro'的方法会忽略重复? – Vahid

0

不使用LINQ。

private static bool AreListsEqual(List<int> list1, List<int> list2) 
{ 
     var areListsEqual = true; 

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

     for (var i = 0; i < list1.Count; i++) 
     { 
      if (list2[i] != list1[i]) 
      { 
       areListsEqual = false; 
      } 
     } 

     return areListsEqual; 
} 
+1

订单不重要,但当数字不在同一顺序时,您的解决方案返回false。 – Vahid

相关问题