Kann .NET überprüfen, ob Liste a alle Elemente in Liste b enthält?

97

Ich habe die folgende Methode:

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

Der Zweck besteht darin, festzustellen, ob eine Liste alle Elemente einer anderen Liste enthält. Es scheint mir, dass so etwas bereits in .NET integriert ist. Ist das der Fall und dupliziere ich die Funktionalität?

Bearbeiten: Ich entschuldige mich dafür, dass ich nicht im Voraus angegeben habe, dass ich diesen Code in Mono Version 2.4.2 verwende.

Matt Haley
quelle
Siehe auch stackoverflow.com/questions/332973/…
Colonel Panic
Ihr Algorithmus ist quadratisch O (nm). Wenn die Listen sortiert sind, sollte in O (n + m) Zeit möglich sein, zu testen, ob eine Teilmenge einer anderen ist.
Colonel Panic

Antworten:

175

Wenn Sie .NET 3.5 verwenden, ist dies ganz einfach:

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

Dies prüft, ob es Elemente gibt, in bdenen nicht enthalten ist a- und invertiert dann das Ergebnis.

Beachten Sie, dass es etwas konventioneller wäre, die Methode generisch anstatt der Klasse zu machen, und es gibt keinen Grund, List<T>stattdessen zu verlangen IEnumerable<T>- daher wäre dies wahrscheinlich vorzuziehen:

public static class LinqExtras // Or whatever
{
    public static bool ContainsAllItems<T>(this IEnumerable<T> a, IEnumerable<T> b)
    {
        return !b.Except(a).Any();
    }
}
Jon Skeet
quelle
1
Dies ist nicht getestet, würde aber nicht zurückgeben. B.Except (a) .Empty (); viel besser lesbar sein?
Nils
7
Nur dass Empty () keinen Booleschen Wert zurückgibt. Es wird eine IEnumerable <T> ohne Elemente zurückgegeben.
Peter Stephens
2
Sie können LINQ für Objekte in Mono verwenden, glaube ich ... aber es wäre hilfreich, wenn Sie zunächst die Anforderungen in der Frage angeben würden. Welche Version von Mono verwenden Sie?
Jon Skeet
1
Wenn die Listen die Länge n und m haben, wie hoch ist die zeitliche Komplexität dieses Algorithmus?
Colonel Panic
1
@ColonelPanic: Unter der Annahme, dass keine Hash-Kollisionen vorliegen, O (n + m).
Jon Skeet
37

In .NET 4 enthalten: Enumerable.All

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

Nur zum Spaß, die Antwort von @ JonSkeet als Erweiterungsmethode:

/// <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();
}
drzaus
quelle
2
ähnlich: Enthält Any = public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Count() > 0; }. Ich habe einige schnelle Leistungsvergleiche versucht haystack.Count() - 1 >= haystack.Except(needle).Count();und Intersectschien die meiste Zeit besser abzuschneiden.
Drzaus
4
Meine Güte ... verwenden Sie Any()nicht Count() > 0: public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Any(); }
drzaus
0

Sie können auch einen anderen Weg verwenden. Override ist gleich und benutze dies

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;
   }
}
user3210251
quelle
2
list l = new List<T>(check);Ich glaube nicht, dass dies kompiliert werden würde, und wenn ja, checkist es völlig unnötig, wie es bereits eine Liste ist
Rohit Vipin Mathews