2009-10-05 6 views
68

que tienen el siguiente método:¿Tiene .NET una forma de verificar si la Lista a contiene todos los elementos en la Lista 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); 
      }); 
     } 
    } 
} 

El propósito es determinar si una lista contiene todos los elementos de otra lista. Me parece que algo así debería estar integrado en .NET, ¿es así y estoy duplicando la funcionalidad?

Editar: Mis disculpas por no mencionar desde el principio que estoy usando este código en la versión Mono 2.4.2.

+0

Véase también https://stackoverflow.com/questions/332973/check-whether-an-array-is-a -subset-of-another –

+0

Su algoritmo es O cuadrático (nm). Si las listas están ordenadas, la prueba de si uno es un subconjunto de otra debería ser posible en O (n + m) tiempo. –

Respuesta

126

Si está utilizando .NET 3.5, es fácil:

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

Esto comprueba si hay elementos en b que no están en a - y luego invierte el resultado.

Nota que sería un poco más convencional para hacer que el método genérico en lugar de la clase, y no hay razón para exigir List<T> en lugar de IEnumerable<T> - por lo que probablemente sería preferido:

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

Esto no se ha probado, pero no devuelve b.Excepto (a) .Empty(); ser mucho más legible? – Nils

+7

Excepto que Empty() no devuelve un valor booleano. Devuelve un IEnumerable sin elementos. –

+0

Esto requiere Linq ¿verdad? Si es así, no creo que esté disponible en Mono, que es lo que estoy usando en este momento. –

29

Justo para la diversión, @ JonSkeet de answer como un método de extensión:

/// <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 para el trabajo adicional – jeremy

+2

de manera similar: Contiene Cualquier = 'bool estático público Contiene cualquier número (este IEnumerable Haystack, IEnumerable needle) {return haystack.Intersect (needle) .Count()> 0; } ' Probé algunas comparaciones rápidas de rendimiento con 'haystack.Count() - 1> = haystack.Except (needle) .Count();' y 'Intersect' parecían funcionar mejor la mayor parte del tiempo. – drzaus

+3

sheesh ... use 'Any()' not 'Count()> 0':' bool estático público Contiene cualquier número (este IEnumerable haystack, IEnumerable needle) {return haystack.Intersect (needle).Alguna(); } ' – drzaus

0

también es posible usar otra forma. Anulación y es igual a utilizar este

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 (check); 'No creo que esto compile y si lo hace, es totalmente innecesario ya que' check' ya es una lista –

13

Incluido en .NET 4: Enumerable.All

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