Pregunta

Quiero obtener la diferencia entre dos conjuntos de entradas en c #. Dado s1 y s2 quiero devolver esos ints que están en s1 y no en s2. Puedo hacer algo como:

    List<int> s1 = new List<int>();
    List<int> s2 = new List<int>();

    foreach (int i in s1)
    {
        if (s1.Contains(i))
        {
            //
        }
        else
        {
            //
        }
    }

Pero me preguntaba si alguien podría señalar algo más limpio. Me gustaría hacer algo como

List<int> omitted = s1.Difference(s2);

¿No está seguro si hay un método existente o una construcción LINQ que alguien pueda señalar? Gracias.

¿Fue útil?

Solución

Creo que quieres HashSet.Except . Es decir, en lugar de usar Listas, use HashSets y luego la operación estará disponible. Este es un tipo mejor si lo que está representando es realmente un 'conjunto' de todos modos. (Si ya tienes una lista, puedes crear un 'nuevo HashSet' a partir de ella).

Otros consejos

IEnumerable<T> a, b;

var added = a.Except(b);
var removed = b.Except(a);
List<int> s1 = new List<int>();
List<int> s2 = new List<int>();

return sl.FindAll( i => !s2.Contains(i) )
from x in s1
where ! s2.contains(x)
select x

Aquí hay dos métodos de extensión que pueden ser útiles cuando necesita encontrar diferencias no ordenadas entre dos IEnumerables (es más o menos lo mismo que la respuesta dada por leppie wrapper en los métodos de extensión):

public class EnumerableDifferences<T>
{
    public IEnumerable<T> Added { get; }
    public IEnumerable<T> Removed { get; }

    public EnumerableDifferences(IEnumerable<T> added, IEnumerable<T> removed)
    {
        Added = added;
        Removed = removed;
    }
}

public static class EnumerableExtensions
{
    public static HashSet<TSource> ToHashSet<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
    {
        return new HashSet<TSource>(source, comparer);
    }

    public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer = null)
    {
        return first
            .ExceptBy(keySelector, second.Select(keySelector), keyComparer);
    }

    public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEnumerable<TKey> keys, IEqualityComparer<TKey> keyComparer = null)
    {
        var secondKeys = keys.ToHashSet(keyComparer);

        foreach (var firstItem in source)
        {
            var firstItemKey = keySelector(firstItem);

            if (!secondKeys.Contains(firstItemKey))
            {
                yield return firstItem;
            }
        }
    }

    public static EnumerableDifferences<TSource> DifferencesBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer = null)
    {
        keyComparer = keyComparer ?? EqualityComparer<TKey>.Default;

        var removed = first.ExceptBy(second, keySelector, keyComparer);
        var added = second.ExceptBy(first, keySelector, keyComparer);

        var result = new EnumerableDifferences<TSource>(added, removed);

        return result;
    }

    public static EnumerableDifferences<TSource> Differences<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer = null)
    {
        return first
            .DifferencesBy(second, x => x, comparer);
    }
}

public static class Program
{
    public static void Main(params string[] args)
    {
        var l1 = new[] { 'a', 'b', 'c' };
        var l2 = new[] { 'a', 'd', 'c' };

        var result = l1.Differences(l2);

        Console.ReadKey();
    }
}

Otra API útil, obtén la diferencia simétrica:

HashSet.SymmetricExceptWith ()

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