Est-ce que .NET a un moyen de vérifier si la liste a contient tous les éléments de la liste b?


98

J'ai la méthode suivante:

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 celui-ci serait déjà intégré à .NET, est-ce le cas et est-ce que je duplique la fonctionnalité?

Edit: Mes excuses pour ne pas avoir déclaré à l'avance que j'utilise ce code sur la version 2.4.2 Mono.



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 un temps O (n + m).
Colonel Panic

Réponses:


176

Si vous utilisez .NET 3.5, c'est simple:

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

Cela vérifie s'il y a des éléments dans blesquels ne figurent pas a- puis inverse le résultat.

Notez qu'il serait légèrement plus conventionnel de rendre la méthode générique plutôt que la classe, et il n'y a aucune raison d'exiger à la List<T>place de IEnumerable<T>- donc ce serait probablement préférable:

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

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

7
Sauf que Empty () ne renvoie pas de booléen. Il renvoie un IEnumerable <T> sans élément.
Peter Stephens

2
Vous pouvez utiliser LINQ to Objects en Mono, je crois ... mais il serait utile que vous indiquiez les exigences dans la question pour commencer. Quelle version de Mono utilisez-vous?
Jon Skeet

1
Si les listes sont de longueur n et m, quelle est la complexité temporelle de cet algorithme?
Colonel Panic

1
@ColonelPanic: En supposant qu'il n'y a pas de collisions de hachage, O (n + m).
Jon Skeet

37

Inclus dans .NET 4: Enumerable.All

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

35

Juste pour le plaisir, la réponse 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
de même: Contient Any = public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Count() > 0; }. J'ai essayé quelques comparaisons rapides de performances haystack.Count() - 1 >= haystack.Except(needle).Count();et j'ai Intersectsemblé faire mieux la plupart du temps.
drzaus

4
sheesh ... use Any()not Count() > 0: public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Any(); }
drzaus

0

Vous pouvez également utiliser une autre méthode. Remplacer égal et utiliser ceci

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 List<T>(check);Je ne pense pas que cela compilerait et si c'est le cas, c'est totalement inutile, car checkc'est déjà une liste
Rohit Vipin Mathews
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.