.NET是否可以检查列表a是否包含列表b中的所有项目?


97

我有以下方法:

namespace ListHelper
{
    public class ListHelper<T>
    {
        public static bool ContainsAllItems(List<T> a, List<T> b)
        {
            return b.TrueForAll(delegate(T t)
            {
                return a.Contains(t);
            });
        }
    }
}

其目的是确定一个列表是否包含另一个列表的所有元素。在我看来,类似的东西已经内置到.NET中了,是这样吗?我是否在复制功能?

编辑:抱歉我没有事先声明我在Mono版本2.4.2上使用此代码。



您的算法是二次O(nm)。如果列表已排序,则应该可以在O(n + m)时间内测试一个列表是否是另一个列表的子集。
Panic Panic

Answers:


175

如果您使用的是.NET 3.5,则很简单:

public class ListHelper<T>
{
    public static bool ContainsAllItems(List<T> a, List<T> b)
    {
        return !b.Except(a).Any();
    }
}

这个检查是否有任何元件在b其不在a-然后反转的结果。

请注意,使该方法泛型而不是使类变得更加常规,并且没有理由要求List<T>代替IEnumerable<T>-因此,这可能是更可取的:

public static class LinqExtras // Or whatever
{
    public static bool ContainsAllItems<T>(this IEnumerable<T> a, IEnumerable<T> b)
    {
        return !b.Except(a).Any();
    }
}

1
这未经测试,但不会返回b.Except(a).Empty(); 更具可读性?
尼尔斯

7
除了Empty()不返回布尔值。它返回一个没有项目的IEnumerable <T>。
彼得·史蒂芬斯

2
我相信您可以在Mono中使用LINQ to Objects ...但是如果您首先提出问题中的要求,这将很有帮助。您正在使用哪个版本的Mono?
乔恩·斯基特

1
如果列表的长度为n和m,此算法的时间复杂度是多少?
Panic Panic'1

1
@ColonelPanic:假设没有哈希冲突,O(n + m)。
乔恩·斯基特

37

包含在.NET 4中: Enumerable.All

public static bool ContainsAll<T>(IEnumerable<T> source, IEnumerable<T> values)
{
    return values.All(value => source.Contains(value));
}

35

只是为了好玩,@ JonSkeet的答案作为扩展方法:

/// <summary>
/// Does a list contain all values of another list?
/// </summary>
/// <remarks>Needs .NET 3.5 or greater.  Source:  https://stackoverflow.com/a/1520664/1037948 </remarks>
/// <typeparam name="T">list value type</typeparam>
/// <param name="containingList">the larger list we're checking in</param>
/// <param name="lookupList">the list to look for in the containing list</param>
/// <returns>true if it has everything</returns>
public static bool ContainsAll<T>(this IEnumerable<T> containingList, IEnumerable<T> lookupList) {
    return ! lookupList.Except(containingList).Any();
}

2
同样:包含Any = public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Count() > 0; }。我尝试了一些快速的性能比较,haystack.Count() - 1 >= haystack.Except(needle).Count();并且Intersect大多数时候似乎做得更好。
drzaus

4
嘘... Any()不要使用Count() > 0public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Any(); }
drzaus

0

您也可以使用其他方式。覆盖等于并使用它

public bool ContainsAll(List<T> a,List<T> check)
{
   list l = new List<T>(check);
   foreach(T _t in a)
   {
      if(check.Contains(t))
      {
         check.Remove(t);
         if(check.Count == 0)
         {
            return true;
         }
      }
      return false;
   }
}

2
list l = new List<T>(check);我认为这不会编译,如果可以编译,则完全没有必要,就像check已经列出的一样
Rohit Vipin Mathews 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.