120 Stimmen

Gibt es in .NET eine Möglichkeit zu prüfen, ob Liste a alle Elemente in Liste b enthält?

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

Deren Zweck ist es, festzustellen, ob eine Liste alle Elemente einer anderen Liste enthält. Es würde mir scheinen, dass so etwas in .NET bereits gebaut werden würde, ist das der Fall und bin ich doppelte Funktionalität?

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

0 Stimmen

0 Stimmen

Dein Algorithmus ist quadratisch O(nm). Wenn die Listen sortiert sind, sollte es möglich sein, zu überprüfen, ob eine Liste eine Teilmenge einer anderen ist, in O(n+m) Zeit.

209voto

Jon Skeet Punkte 1325502

Wenn Sie .NET 3.5 verwenden, ist es einfach:

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

Dies überprüft, ob es Elemente in b gibt, die nicht in a sind - und kehrt dann das Ergebnis um.

Beachten Sie, dass es etwas konventioneller wäre, die Methode generisch zu machen, anstatt die Klasse, und es besteht kein Grund, List anstelle von IEnumerable zu verlangen - daher wäre dies wahrscheinlich bevorzugt:

public static class LinqExtras // Oder was auch immer
{
    public static bool ContainsAllItems(this IEnumerable a, IEnumerable b)
    {
        return !b.Except(a).Any();
    }
}

1 Stimmen

Das ist nicht getestet, aber wäre return b.Except(a).Empty(); nicht viel lesbarer ?

7 Stimmen

Mit Ausnahme von Empty() gibt keine Rückgabe eines booleschen Wertes. Es gibt eine IEnumerable-Rückgabe ohne Elemente.

0 Stimmen

Dies erfordert also Linq, richtig? Wenn ja, denke ich nicht, dass dies in Mono verfügbar ist, was ich derzeit verwende.

51voto

Thomas Punkte 16579

Enthalten in .NET 4: Enumerable.All

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

0 Stimmen

Enumerable.All existierte vor .Net 4.0, und hier handelt es sich um eine O(N^2)-Operation im Vergleich zu der in der akzeptierten Antwort.

36voto

drzaus Punkte 22843

Nur zum Spaß, @JonSkeets Antwort als Erweiterungsmethode:

/// 
/// Enthält eine Liste alle Werte einer anderen Liste?
/// 
/// Benötigt .NET 3.5 oder höher.  Quelle:  https://stackoverflow.com/a/1520664/1037948 
/// Listenwerttyp
/// die größere Liste, die wir überprüfen
/// die Liste, die in der enthaltenden Liste gesucht werden soll
/// true, wenn alles vorhanden ist
public static bool ContainsAll(this IEnumerable containingList, IEnumerable lookupList) {
    return !lookupList.Except(containingList).Any();
}

2 Stimmen

Ebenso: Enthält Eine beliebige = public static bool ContainsAny(this IEnumerable haystack, IEnumerable needle) { return haystack.Intersect(needle).Count() > 0; }. Ich habe einige schnelle Leistungsvergleiche zu haystack.Count() - 1 >= haystack.Except(needle).Count(); und Intersect schien die meiste Zeit besser abzuschneiden.

4 Stimmen

Sheesh...verwenden Sie Any() und nicht Count() > 0: public static bool ContainsAny(this IEnumerable haystack, IEnumerable needle) { return haystack.Intersect(needle).Any(); }

3voto

Ich kenne einen Weg mit LinQ-Methoden. Es ist ein bisschen seltsam zu lesen, funktioniert aber ziemlich gut

var motherList = new List { "Hallo", "Welt", "Benutzer" };
var sonList = new List { "Hallo", "Benutzer" };

Du möchtest prüfen, ob sonList vollständig in motherList enthalten ist

Um dies zu tun:

sonList.All(str => motherList.Any(word => word == str));

// Wörtlich übersetzt würde es bedeuten "Für jedes Element 
// in sonList überprüfen, ob es in motherList ist"

Bitte versuche es aus und sieh, ob es dort auch funktioniert. Hoffe, es hilft ;-)

0 Stimmen

Dies funktioniert. Bitte korrigieren Sie jedoch den Tippfehler in dieser Zeile: bool result = sonList.All(str => motherList.Any(word => word == str));

-1voto

user3210251 Punkte 141

Sie könnten auch einen anderen Weg verwenden. Überschreiben Sie Equals und verwenden Sie dies

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

2 Stimmen

list l = new List(check); Ich glaube nicht, dass das kompilieren würde, und wenn doch, ist es völlig unnötig, da check bereits eine Liste ist

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X