【问题标题】:In C#, What is the best way to see if a list contains another list?在 C# 中,查看列表是否包含另一个列表的最佳方法是什么?
【发布时间】:2013-10-29 00:47:50
【问题描述】:

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

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”的方法?

【问题讨论】:

标签: c# linq collections


【解决方案1】:
if (!list2.Except(list).Any())

【讨论】:

    【解决方案2】:

    喜欢 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;
    }
    

    如果list1HashSet,则产生O(list2.Count)

    【讨论】:

    • 使用 Linq 的 Except() 是一个 O(mn) 操作,我相信,而 HashSet.IsSubsetOf() 是 O(n)。
    • @NicholasCarey 好吧,取决于定义。 Except 需要两个 IEnumerables,从右侧构造 HashSet 并在左侧迭代,在 HashSet 上调用 Add 方法。据我所知,这给出了m + nAdd 方法需要固定时间。 IsSubset 有这一行 HashSet&lt;T&gt; hashSet = other as HashSet&lt;T&gt;;,这使得无需从 list1 构造 HashSet 就产生了巨大的差异。然后它确实只剩下O(n),其中n = list1.Count
    • @NicholasCarey Enumerable.Except 实际上在枚举期间创建了一个临时哈希表。这使它成为 O(n+m),而不是 O(nm)。
    【解决方案3】:

    怎么样,

    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");
    

    【讨论】:

      【解决方案4】:

      这个怎么样

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-29
        • 2017-01-13
        • 1970-01-01
        相关资源
        最近更新 更多