有没有办法在c#中获得两组对象之间的差异?

时间:2023-01-17 21:30:35

I want to get the difference between two sets of ints in c#. Given s1 and s2 I want to return those ints which are in s1 and not in s2. I can do something such as:

我想在c#中获得两组int之间的区别。给定s1和s2我想返回那些在s1而不在s2中的int。我可以做一些事情,比如:

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

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

But I was wondering if anyone can point out anything cleaner. I would like to do something such as

但我想知道是否有人能指出更清洁的东西。我想做点什么

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

Not sure if there is an existing method or a LINQ construct that anyone might be able to point out? Thank you.

不确定是否有任何人可能指出的现有方法或LINQ结构?谢谢。

5 个解决方案

#1


20  

I think you want HashSet.Except. That is, rather than use Lists, use HashSets, and then the operation is available. This is a better type if what you are representing is really a 'set' anyway. (If you already have a list, you can just create a 'new HashSet' out of it.)

我想你想要HashSet.Except。也就是说,使用HashSets,而不是使用Lists,然后操作可用。如果您所表示的内容实际上是一个“设置”,这是一个更好的类型。 (如果你已经有了一个列表,你可以从中创建一个'新的HashSet'。)

#2


21  

IEnumerable<T> a, b;

var added = a.Except(b);
var removed = b.Except(a);

#3


2  

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

return sl.FindAll( i => !s2.Contains(i) )

#4


1  

from x in s1
where ! s2.contains(x)
select x

#5


0  

Here are two extension methods that might come handy when you need to find unordered differences between two IEnumerable (it's more or less the same as the answer given by leppie wrapper into extension methods):

当你需要找到两个IEnumerable之间的无序差异时,这两个扩展方法可能很方便(它与leppie包装器给出的扩展方法的答案大致相同):

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

#1


20  

I think you want HashSet.Except. That is, rather than use Lists, use HashSets, and then the operation is available. This is a better type if what you are representing is really a 'set' anyway. (If you already have a list, you can just create a 'new HashSet' out of it.)

我想你想要HashSet.Except。也就是说,使用HashSets,而不是使用Lists,然后操作可用。如果您所表示的内容实际上是一个“设置”,这是一个更好的类型。 (如果你已经有了一个列表,你可以从中创建一个'新的HashSet'。)

#2


21  

IEnumerable<T> a, b;

var added = a.Except(b);
var removed = b.Except(a);

#3


2  

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

return sl.FindAll( i => !s2.Contains(i) )

#4


1  

from x in s1
where ! s2.contains(x)
select x

#5


0  

Here are two extension methods that might come handy when you need to find unordered differences between two IEnumerable (it's more or less the same as the answer given by leppie wrapper into extension methods):

当你需要找到两个IEnumerable之间的无序差异时,这两个扩展方法可能很方便(它与leppie包装器给出的扩展方法的答案大致相同):

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