25

C#の2セットのintの違いを取得したいと思います。s1とs2が与えられた場合、s2にはなくs1にあるintを返したいと思います。私は次のようなことをすることができます:

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

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

しかし、私は誰かがもっときれいなものを指摘できるかどうか疑問に思いました。こんなことをしたい

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

誰もが指摘できる可能性のある既存のメソッドまたはLINQ構造があるかどうかわかりませんか?ありがとうございました。

4

6 に答える 6

33
IEnumerable<T> a, b;

var added = a.Except(b);
var removed = b.Except(a);
于 2009-04-30T09:54:10.147 に答える
30

HashSet.Exceptが必要だと思います。つまり、リストを使用するのではなく、HashSetsを使用すると、操作が使用可能になります。とにかく、あなたが表現しているものが本当に「セット」である場合、これはより良いタイプです。(すでにリストがある場合は、そのリストから「新しいHashSet」を作成できます。)

于 2009-04-30T09:45:49.510 に答える
3

もう1つの便利なAPIは、対称差を取得します。

HashSet.SymmetricExceptWith()

于 2018-09-17T22:49:17.727 に答える
2
List<int> s1 = new List<int>();
List<int> s2 = new List<int>();

return sl.FindAll( i => !s2.Contains(i) )
于 2009-04-30T09:49:48.893 に答える
1
s1のxから
どこ !s2.contains(x)
xを選択
于 2009-04-30T09:49:42.573 に答える
0

2つのIEnumerable間の順序付けられていない違いを見つける必要がある場合に便利な2つの拡張メソッドを次に示します(これは、拡張メソッドへの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();
    }
}
于 2017-12-28T15:03:08.167 に答える