2009-10-05 6 views
68

J'ai la méthode suivante:Est-ce que .NET permet de vérifier si la liste a contient tous les éléments de la liste b?

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

Le but est de déterminer si une liste contient tous les éléments d'une autre liste. Il me semble que quelque chose comme ça serait déjà intégré dans .NET, est-ce le cas et est-ce que je duplique les fonctionnalités? Edit: Toutes mes excuses pour ne pas avoir dit au début que j'utilise ce code sur la version 2.4.2 de Mono.

+0

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

+0

Votre algorithme est quadratique O (nm). Si les listes sont triées, tester si l'une est un sous-ensemble d'une autre devrait être possible en O (n + m) temps. –

Répondre

126

Si vous utilisez .NET 3.5, il est facile:

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

Cela permet de vérifier s'il y a des éléments qui ne sont pas b dans a - et intervertit le résultat.

Notez que ce serait un peu plus conventionnel pour rendre la méthode générique plutôt que la classe, et il n'y a aucune raison d'exiger List<T> au lieu de IEnumerable<T> - donc ce serait probablement préféré:

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

Ceci n'a pas été testé, mais ne retournera pas b.Except (a) .Empty(); être beaucoup plus lisible? – Nils

+7

Sauf que Empty() ne renvoie pas de booléen. Il renvoie un IEnumerable sans éléments. –

+0

Cela nécessite Linq? Si oui, je ne pense pas que ce soit disponible en Mono, qui est ce que j'utilise en ce moment. –

29

Juste pour le plaisir, @answer de JonSkeet comme méthode d'extension:

/// <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 pour le travail supplémentaire – jeremy

+2

De même: Contient Any = 'public static bool ContainsAny (ce IEnumerable haystack, IEnumerable aiguille) {return haystack.Intersect (aiguille) .Count()> 0; } '. J'ai essayé quelques comparaisons de performances rapides à 'haystack.Count() - 1> = haystack.Except (aiguille) .Count();' et 'Intersect' semblé faire mieux la plupart du temps. – drzaus

+3

sheesh ... utilise 'Any()' pas 'Count()> 0':' public static bool ContainsAny (cette IEnumerable haystack, aiguille IEnumerable ) {return haystack.Intersect (aiguille).Tout(); } ' – drzaus

0

Vous pouvez également utiliser une autre façon. Surchargent equals et utiliser cette

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

' liste l = nouvelle Liste (vérifier); 'Je ne pense pas que cela compilerait et si c'est le cas, c'est totalement inutile car' check' est déjà une liste –

13

Inclus dans .NET 4: Enumerable.All

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