2009-10-05 14 views
68

Ich habe die folgende Methode:Kann .NET prüfen, ob Liste a alle Elemente in Liste b enthält?

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 zu bestimmen, ist, wenn eine Liste alle Elemente einer anderen Liste enthält. Es scheint mir, dass sowas schon in .NET eingebaut sein würde, ist das der Fall und verdopple ich die Funktionalität?

Edit: Ich entschuldige mich, dass ich diesen Code nicht auf Mono Version 2.4.2 verwende.

+0

Siehe auch https://stackoverflow.com/questions/332973/check-whether-an-array-is-a -subset-of-another –

+0

Ihr Algorithmus ist quadratisch O (nm). Wenn die Listen sortiert sind, sollte es möglich sein, in O (n + m) -Zeit zu testen, ob eine Teilmenge einer anderen ist. –

Antwort

126

Wenn Sie .NET 3.5, indem es einfach:

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

Diese prüft, ob es irgendwelche Elemente in b die nicht in a - und invertiert dann das Ergebnis.

Beachten Sie, dass es etwas konventionelleren wäre, die Methode Generika anstatt die Klasse zu machen, und es gibt keinen Grund List<T> statt IEnumerable<T> zu verlangen - so würde dies wahrscheinlich bevorzugt werden:

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

Dies ist ungeprüft, würde aber nicht zurückgeben b.Except (a) .Empty(); viel besser lesbar sein? – Nils

+7

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

+0

Das erfordert Linq richtig? Wenn dem so ist, denke ich nicht, dass das in Mono verfügbar ist, was ich gerade benutze. –

29

Nur zum Spaß, @ JonSkeet des answer als Erweiterung Methode:

/// <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

+1 für die zusätzliche Arbeit – jeremy

+2

ähnlich: Enthält Any = 'öffentliche statische bool ContainsAny (diese IEnumerable Heuhaufen, IEnumerable Nadel) {zurück Heuhaufen.Intersect (Nadel) .Count()> 0; } '. Ich habe einige schnelle Leistungsvergleiche mit 'heystack.Count() - 1> = heystack.Except (nadel) .Count();' und 'Intersect 'versucht, die meiste Zeit besser zu machen. – drzaus

+3

sheesh ... benutze 'Any()' nicht 'Count()> 0':' public statisch bool ContainsAny (dieser IEnumerable Heuhaufen, IEnumerable Nadel) {zurück Heuhaufen.Intersect (Nadel).Irgendein(); } ' – drzaus

0

Sie könnten auch eine andere Art und Weise nutzen. Außer Kraft setzen gleich und verwenden diese

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 Liste (check); 'Ich glaube nicht, dass dies kompilieren würde, und wenn dies der Fall ist, ist seine völlig unnötige 'check' bereits eine Liste –

13

Eingeschlossen in .NET 4: Enumerable.All

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