2010-07-18 77 views
65

比較兩個集合中每個元素的字段/屬性時,確定一個IEnumerable是否包含另一個IEnumerable的所有元素的最快方法是什麼?檢查一個IEnumerable是否包含另一個IEnumerable的所有元素


public class Item 
{ 
    public string Value; 

    public Item(string value) 
    { 
     Value = value; 
    } 
} 

//example usage 

Item[] List1 = {new Item("1"),new Item("a")}; 
Item[] List2 = {new Item("a"),new Item("b"),new Item("c"),new Item("1")}; 

bool Contains(IEnumerable<Item> list1, IEnumerable<Item>, list2) 
{ 
    var list1Values = list1.Select(item => item.Value); 
    var list2Values = list2.Select(item => item.Value); 

    return //are ALL of list1Values in list2Values? 
} 

Contains(List1,List2) // should return true 
Contains(List2,List1) // should return false 
+1

哪種方式圓您的列表?你想檢查列表1中的所有項目是否在列表2中,或者列表2中的所有項目是否在列表1中? – 2010-07-18 06:23:20

回答

94

除非您跟蹤並維護某個狀態,以確定某個集合中的所有值是否包含在另一個集合中,否則沒有「快速方法」來執行此操作。如果你只有IEnumerable<T>對付,我會用Intersect

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

這樣做的性能應該是非常合理的,因爲Intersect()將每個列表枚舉一次。另外,如果基礎類型是ICollection<T>而不是僅僅IEnumerable<T>,則第二次調用Count()將是最佳的。

+0

我做了一些測試,這種方法似乎比其他方法運行得更快。謝謝你的提示。 – 2010-07-18 11:21:16

+0

我想你的意思是'var allOfList2IsInList1 = list1.Intersect(list2).Count()== list2.Count();' – dan 2012-11-23 14:51:29

+2

@fsmmu:不,我沒有。第一次調用查找列表1和列表2的交集中有多少個項目。第二個調用查找列表1中有多少項目。如果這些編號相同,則列表1中的所有列表都在列表2中,如根據OP的題。 – 2012-11-23 16:09:51

2

LINQ的運營商SequenceEqual也會正常工作(但是是可枚舉的項目以相同的順序是敏感的)

return list1Uris.SequenceEqual(list2Uris); 
18

C#3.5+

使用Enumerable.All<TSource>確定列表1中包含所有List2項目:

bool hasAll = list2Uris.All(itm2 => list1Uris.Contains(itm2)); 

當list1包含甚至超過list2的所有項目時,這也會起作用。

+8

Ouch在'All()'調用中的'Contains()'調用的性能影響。 – 2010-07-18 08:24:36

+0

你也可以將它移動到組方法:bool hasAll = list2Uris.All(list1Uris.Contains); – jimpanzer 2014-01-10 08:37:57

+0

我的IEnumerable 類型的這種解決方案將提供n * m的性能。 – 2016-08-08 14:17:05

31

你也可以使用除了從第一列表中存在的第二個列表中的所有值去掉,然後檢查是否所有值已被刪除:

var allOfList1IsInList2 = !list1.Except(list2).Any(); 

該方法具有不要求兩個優勢調用Count()。

+0

這也很適合查找List1中的內容,而不是List2中的內容; – Homer 2014-06-20 18:54:33

+5

這適用於list1具有重複值的情況。接受的答案不是。 – dbc 2016-04-04 01:33:15

4

標記爲答案的解決方案在重複情況下會失敗。如果您的IEnumerable只包含不同的值,那麼它會通過。

下面的答案是2只列出了與循環:

 int aCount = a.Distinct().Count(); 
     int bCount = b.Distinct().Count(); 

     return aCount == bCount && 
       a.Intersect(b).Count() == aCount; 
3

肯特的答案是細而短,但他提供的解決方案總是需要在整個第一集合迭代。這裏是源代碼:

public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer) 
{ 
    if (first == null) 
     throw Error.ArgumentNull("first"); 
    if (second == null) 
     throw Error.ArgumentNull("second"); 
    return Enumerable.IntersectIterator<TSource>(first, second, comparer); 
} 

private static IEnumerable<TSource> IntersectIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer) 
{ 
    Set<TSource> set = new Set<TSource>(comparer); 
    foreach (TSource source in second) 
     set.Add(source); 
    foreach (TSource source in first) 
    { 
     if (set.Remove(source)) 
      yield return source; 
    } 
} 

這並非總是必需的。所以,這裏是我的解決方案:

public static bool Contains<T>(this IEnumerable<T> source, IEnumerable<T> subset, IEqualityComparer<T> comparer) 
{ 
    var hashSet = new HashSet<T>(subset, comparer); 
    if (hashSet.Count == 0) 
    { 
     return true; 
    } 

    foreach (var item in source) 
    { 
     hashSet.Remove(item); 
     if (hashSet.Count == 0) 
     { 
      break; 
     } 
    } 

    return hashSet.Count == 0; 
} 

其實,你應該考慮使用ISet<T>HashSet<T>)。它包含所有必需的設置方法。 IsSubsetOf你的情況。

-1

,你可以用這個方法來比較兩個列表

//Method to compare two list 
    private bool Contains(IEnumerable<Item> list1, IEnumerable<Item> list2) 
    { 
     bool result; 

     //Get the value 
     var list1WithValue = list1.Select(s => s.Value).ToList(); 
     var list2WithValue = list2.Select(s => s.Value).ToList(); 

     result = !list1WithValue.Except(list2WithValue).Any(); 

     return result; 
    } 
+0

幾乎與3年前相同的答案:http://stackoverflow.com/a/16967827/5282087 – Dragomok 2017-02-07 18:59:30

0

您應該使用,而不是數組HashSet的。

例子:

List1.SetEquals(List2); //returns true if the collections contains exactly same elements no matter the order they appear in the collection 

Reference

唯一HasSet限制是,我們不能像列表中的索引項獲得通過,也沒有像字典鍵時,會項目。所有你能做的就是列舉出來(每個,而等)

請讓我知道這是否爲你的作品

相關問題