Pregunta

¿Alguna idea sobre cómo verificar si esa lista es un subconjunto de otra?

Específicamente, tengo

List<double> t1 = new List<double> { 1, 3, 5 };
List<double> t2 = new List<double> { 1, 5 };

¿Cómo verificar que t2 es un subconjunto de t1, usando LINQ?

¿Fue útil?

Solución

bool isSubset = !t2.Except(t1).Any();

Otros consejos

Use HashSet en lugar de List si trabaja con conjuntos. Entonces puede simplemente usar IsSubsetOf ()

HashSet<double> t1 = new HashSet<double>{1,3,5};
HashSet<double> t2 = new HashSet<double>{1,5};

bool isSubset = t2.IsSubsetOf(t1);

Lamento que no use LINQ. :-(

Si necesita usar listas, la solución de @ Jared funciona con la advertencia de que deberá eliminar cualquier elemento repetido que exista.

Si está pruebas unitarias , también puede utilizar Método CollectionAssert.IsSubsetOf :

CollectionAssert.IsSubsetOf(subset, superset);

En el caso anterior esto significaría:

CollectionAssert.IsSubsetOf(t2, t1);

La solución de @ Cameron como método de extensión:

public static bool IsSubsetOf<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    return !a.Except(b).Any();
}

Uso:

bool isSubset = t2.IsSubsetOf(t1);

(Esto es similar, pero no exactamente igual al publicado en el blog de @ Michael)

Esta es una solución significativamente más eficiente que las otras publicadas aquí, especialmente la solución principal:

bool isSubset = t2.All(elem => t1.Contains(elem));

Si puede encontrar un solo elemento en t2 que no esté en t1, entonces sabrá que t2 no es un subconjunto de t1. La ventaja de este método es que se realiza todo en el lugar, sin asignar espacio adicional, a diferencia de las soluciones que usan .Except o .Intersect. Además, esta solución puede romperse tan pronto como encuentre un solo elemento que viole la condición del subconjunto, mientras que los demás continúan buscando. A continuación se muestra la forma larga óptima de la solución, que es solo marginalmente más rápida en mis pruebas que la solución abreviada anterior.

bool isSubset = true;
foreach (var element in t2) {
    if (!t1.Contains(element)) {
        isSubset = false;
        break;
    }
}

Hice un análisis de rendimiento rudimentario de todas las soluciones, y los resultados son drásticos. Estas dos soluciones son aproximadamente 100 veces más rápidas que las soluciones .Except () y .Intersect (), y no utilizan memoria adicional.

Partiendo de las respuestas de @Cameron y @Neil, escribí un método de extensión que utiliza la misma terminología que la clase Enumerable.

/// <summary>
/// Determines whether a sequence contains the specified elements by using the default equality comparer.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">A sequence in which to locate the values.</param>
/// <param name="values">The values to locate in the sequence.</param>
/// <returns>true if the source sequence contains elements that have the specified values; otherwise, false.</returns>
public static bool ContainsAll<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> values)
{
    return !values.Except(source).Any();
}
  

Aquí verificamos que si hay algún elemento presente en la lista secundaria (es decir, t2 ) que no está contenido en la lista principal (es decir, t1 ). Si no hay ninguno tal existe entonces la lista es un subconjunto del otro

por ejemplo:

bool isSubset = !(t2.Any(x => !t1.Contains(x)));

Prueba esto

static bool IsSubSet<A>(A[] set, A[] toCheck) {
  return set.Length == (toCheck.Intersect(set)).Count();
}

La idea aquí es que Intersect solo devolverá los valores que están en ambas matrices. En este punto, si la longitud del conjunto resultante es la misma que la del conjunto original, entonces todos los elementos en "conjunto" también están en " cheque " y por lo tanto " set " es un subconjunto de `` toCheck ''

Nota: Mi solución no funciona si " set " tiene duplicados No lo voy a cambiar porque no quiero robar los votos de otras personas.

Sugerencia: voté por la respuesta de Cameron.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top