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 der 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 keinen Grund gibt, List anstelle von IEnumerable zu benötigen - daher wäre dies wahrscheinlich bevorzugt:

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

1 Stimmen

Dies ist ungetestet, aber würde return b.Except(a).Empty(); nicht viel lesbarer sein?

7 Stimmen

Außer dass Empty() keinen booleschen Wert zurückgibt. Es gibt stattdessen ein IEnumerable ohne Elemente zurück.

0 Stimmen

Dies erfordert Linq, richtig? Wenn ja, glaube 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<T>(IEnumerable<T> source, IEnumerable<T> 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 Gegensatz 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 
/// Listentyp
/// die größere Liste, die überprüft wird
/// die Liste, nach der in der enthaltenden Liste gesucht wird
/// true, wenn alles vorhanden ist
public static bool ContainsAll(this IEnumerable containingList, IEnumerable lookupList) {
    return ! lookupList.Except(containingList).Any();
}

2 Stimmen

Ebenso: Enthält Irgendeine = 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(); versucht und Intersect schien die meiste Zeit besser zu sein.

4 Stimmen

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

3voto

Ich kenne einen Weg, um LinQ-Methoden zu verwenden. Es ist etwas seltsam zu lesen, funktioniert aber ziemlich gut

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

Sie möchten überprüfen, ob sonList vollständig in motherList enthalten ist

Um dies zu tun:

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

// Wörtlich gelesen würde es heißen "Für jedes Element in sonList
// testen, ob es in motherList enthalten ist

Bitte probieren Sie es aus und sehen Sie, ob es auch dort funktioniert. Hoffe es hilft ;-)

0 Stimmen

Dies funktioniert. Aber bitte korrigieren Sie 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 nutzen. Überschreiben Sie equals und nutzen 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