.NET'in Liste a'nın Liste b'deki tüm öğeleri içerip içermediğini kontrol etmenin bir yolu var mı?


100

Aşağıdaki yönteme sahibim:

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

Bunun amacı, bir Listenin başka bir listenin tüm unsurlarını içerip içermediğini belirlemektir. Bana öyle geliyor ki, bunun gibi bir şey zaten .NET'te yerleşik olacaktı, durum bu mu ve ben işlevselliği mi çoğaltıyorum?

Düzenleme: Bu kodu Mono sürüm 2.4.2'de kullandığımı açıkça belirtmediğim için özür dilerim.



Algoritmanız ikinci dereceden O (nm). Listeler sıralanırsa, birinin diğerinin alt kümesi olup olmadığını test etmek O (n + m) süresinde mümkün olmalıdır.
Albay Panic

Yanıtlar:


178

.NET 3.5 kullanıyorsanız, bu kolaydır:

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

Herhangi unsurlarının olup olmadığını Bu kontroller de bhangi değildir a- ve sonra sonuç tersine çevirir.

Yöntemi sınıftan ziyade genel hale getirmenin biraz daha geleneksel olacağını ve List<T>bunun yerine zorunlu kılmanın bir nedeni olmadığını unutmayın IEnumerable<T>- bu nedenle muhtemelen bu tercih edilir:

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

1
Bu test edilmemiştir, ancak döndürülmez b. (A) dışında. çok daha okunabilir mi?
Nils

7
Empty () 'nin bir boole döndürmemesi dışında. Öğe içermeyen bir IEnumerable <T> döndürür.
Peter Stephens

2
LINQ to Objects in Mono kullanabilirsiniz, inanıyorum ... ama başlamak için soruda gereksinimleri belirtmeniz faydalı olacaktır. Mono'nun hangi sürümünü kullanıyorsunuz?
Jon Skeet

1
Listelerin uzunluğu n ve m ise, bu algoritmanın zaman karmaşıklığı nedir?
Albay Panic

1
@ColonelPanic: Karma çarpışmalar olmadığı varsayıldığında, O (n + m).
Jon Skeet

39

.NET 4'e dahildir: Enumerable.All

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

35

Sadece eğlence için @ JonSkeet'in bir uzatma yöntemi olarak cevabı :

/// <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
benzer şekilde: Any = İçerir public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Count() > 0; }. Bazı hızlı performans karşılaştırmalarını denedim haystack.Count() - 1 >= haystack.Except(needle).Count();ve Intersectçoğu zaman daha iyisini yaptım.
drzaus

4
sheesh ... kullanım Any()değil Count() > 0: public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Any(); }
drzaus

0

Başka bir yol da kullanabilirsin. Eşitleri geçersiz kıl ve bunu kullan

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);Bunun derleneceğini sanmıyorum ve eğer öyleyse check, zaten bir liste olduğu gibi tamamen gereksiz
Rohit Vipin Mathews
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.