.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でこのコードを使用していることを前もって述べなかったことに対する私の謝罪。



アルゴリズムは2次O(nm)です。リストが並べ替えられている場合、O(n + m)時間で、あるリストが別のサブセットであるかどうかをテストできるはずです。
大佐パニック

回答:


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>を返します。
Peter Stephens、

2
LINQ to ObjectsをMonoで使用できると思いますが...質問の要件を最初に述べておけば助かります。どのバージョンのMonoを使用していますか?
Jon Skeet、

1
リストが長さnおよびmである場合、このアルゴリズムの時間の複雑さはどのくらいですか?
大佐パニック

1
@ColonelPanic:ハッシュの衝突がないと仮定すると、O(n + m)。
Jon Skeet、2016年

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 2013年

4
sheesh ...使用しAny()ないでくださいCount() > 0public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Any(); }
drzaus 2013年

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.