2013-10-29 52 views
2

如果我有一个字符串列表,确定另一个列表中的每个元素是否包含在这个列表中的最佳方法是什么。例如:在C#中,查看列表是否包含另一个列表的最佳方法是什么?

List<string> list = new List<string>(); 
list.Add("Dog"); 
list.Add("Cat"); 
list.Add("Bird"); 

List<string> list2 = new List<string>(); 
list.Add("Dog"); 
list.Add("Cat"); 

if (list.ContainsList(list2)) 
{ 
     Console.Write("All items in list2 are in list1") 
} 

我想确定是否有像这样的“ContainsList”方法?

+1

好讨论这个http://stackoverflow.com/questions/332973/linq-check-whether-an-array-另一个是@leora的子集 – ojhawkins

回答

6
if (!list2.Except(list).Any()) 
+0

神奇的是它和'HashSet'解决方案一样快。 –

4

Loved SLaks版本。为了完整,您可以在执行设置操作时使用HashSet方法IsSubsetOf(同时检查IsSupersetOf方法)。这种方法有利有弊。下面的代码显示了一个示例:

var list1 = new HashSet<string>{ "Dog", "Cat", "Bird" }; 

var list2 = new HashSet<string>{ "Dog", "Cat" }; 

if (list2.IsSubsetOf(list1)) 
{ 
     Console.Write("All items in list2 are in list1"); 
} 

Except方法本质上是流式传输。在查询list2.Except(list1)list1被完全缓冲到内存中,并且通过list2一次迭代一个项目。 IsSubsetOf热切地以相反的方式工作。当你有大量的数据时,这会开始有所作为。


分析最坏情况下的性能,下面是Except实现在Monos Enumerable一些代码(dotPeek给出了非常相似的结果,只是少可读性)

var items = new HashSet<TSource> (second, comparer); //list1.Count 

foreach (var element in first)      //list2.Count 
    if (items.Add (element))       //constant time 
     yield return element; 

的结果O(list1.Count + list2.Count),循环不能嵌套。

IsSubset具有下一个方法调用,如果第二IEnumerableHashSet(经由dotPeek反编译):

private bool IsSubsetOfHashSetWithSameEC(HashSet<T> other) 
{ 
    foreach (T obj in this)   //list2.Count 
     if (!other.Contains(obj)) //constant time 
      return false; 

    return true; 
} 

O(list2.Count)得到的IF list1HashSet

+2

使用Linq的'Except()'是一个O(mn)操作,我相信,而'HashSet.IsSubsetOf()'是O(n)。 –

+0

@NicholasCarey好,取决于定义。 'Except'接受两个'IEnumerable',从右侧构造'HashSet'并在'HashSet'上迭代左侧调用'Add'方法。据我所知,这给出了“m + n”。 'Add'方法需要一段时间。 'IsSubset'有这一行'HashSet hashSet =其他为HashSet ;'这会产生巨大的差异,不需要从'list1'构造'HashSet'。然后它只剩下'O(n)',其中n ='list1.Count'。 –

+0

@NicholasCarey Enumerable.Except'实际上在枚举过程中创建了一个临时哈希表。这使它成为O(n + m),而不是O(nm)。 –

0

怎么样,

var list1 = new List<string>{"Dog","Cat","Bird"}; 
var list2 = new List<string>{"Dog","Cat"}; 

if (list1.Union(list2).SequenceEqual(list1)) 
    Console.Write("All items in list2 are in list1"); 
0

如何在这里这个

list1.intersect (list2).ToList().Foreach ((x)=> 
{ 
Console.Writeline (x) 
}); 
相关问题