Intersect()の反対


275

次のように、Intersectを使用して2つのコレクション間の一致を見つけることができます。

// Assign two arrays.
int[] array1 = { 1, 2, 3 };
int[] array2 = { 2, 3, 4 };
// Call Intersect extension method.
var intersect = array1.Intersect(array2);
// Write intersection to screen.
foreach (int value in intersect)
{
    Console.WriteLine(value); // Output: 2, 3
}

ただし、私が達成したいのはその逆です。あるコレクションのアイテムのうち、他のコレクションにはないものをリストしたいと思います

// Assign two arrays.
int[] array1 = { 1, 2, 3 };
int[] array2 = { 2, 3, 4 };
// Call "NonIntersect" extension method.
var intersect = array1.NonIntersect(array2); // I've made up the NonIntersect method
// Write intersection to screen.
foreach (int value in intersect)
{
    Console.WriteLine(value); // Output: 4
}

13
してくださいあなたは、出力、または1と4と4をしたいかどうかを確認
ØyvindBråthen

@ oyvind-knobloch-brathenはい、私は4のみ希望します
Peter Bridger

23
補足として、このタイプのセットは対称差と呼ばれます。
マイクT

19
技術的には、対称差は[1、4]になります。Peterは、array1にない(つまり、4)array2の要素だけを必要としていたので、これを相対補完(別名、集合論的差異)と
呼びます

回答:


376

述べたように、結果として4を取得したい場合は、次のようにすることができます。

var nonintersect = array2.Except(array1);

実際の非交差(1と4の両方)が必要な場合は、これでうまくいくはずです。

var nonintersect = array1.Except(array2).Union( array2.Except(array1));

これは最もパフォーマンスの高いソリューションではありませんが、小さなリストの場合は問題なく機能します。


2
より良いパフォーマンスのソリューションは何でしょうか?ありがとう!
シャナバス2012年

6
おそらく2つの入れ子になったforループを使用することでより速く実行できますが、コードはこれよりもはるかに汚くなります。これも読みやすさを考慮して、非常に読みやすいので、このバリアントを明確に使用します。
ØyvindBråthen

5
追加するだけの副次的なポイント、次の場合:int [] before = {1、2、3}; int [] after = {2、3、3、4}; そして、Exceptを使用して、「before」以降に「after」に追加されたものを見つけようとします。var diff = after.Except(before); 「diff」には3、4ではなく4が含まれます。つまり、予期しない結果をもたらす重複要素に注意してください
Paul Ryland 2013

これでパフォーマンスが向上しますか?array1.AddRange(array2.Except(array1));
LBW

86

使用できます

a.Except(b).Union(b.Except(a));

または使用できます

var difference = new HashSet(a);
difference.SymmetricExceptWith(b);

2
SymmetricExceptWith()の興味深い使用法、私はそのアプローチを考えていなかったでしょう
Peter Bridger

SymmetricExceptWithおそらく私のお気に入りの方法です。
Ash Clarke

6
実際のアプリケーションで2つを比較したところ、それぞれに約125個の文字列のリストがいくつかありました。最初のアプローチを使用すると、実際にはそのサイズのリストの方が高速ですが、0.5ミリ秒未満の両方のアプローチとほとんど同じです。
Dan

1
BCLがこのためのLinq拡張メソッドを持っているとよいでしょう。脱落のようです。
Drew Noakes、2015年

誰かがSymmetricExceptWithをベンチマークし、それをはるかに速く見つけました:skylark-software.com/2011/07/linq-and-set-notation.html
Colin

11

このコードは、各シーケンスを1回だけ列挙しSelect(x => x)、結果を非表示にしてクリーンなLinqスタイルの拡張メソッドを取得します。HashSet<T>ランタイムが使用されるのはO(n + m)、ハッシュが適切に分散されている場合です。どちらのリストでも重複する要素は省略されます。

public static IEnumerable<T> SymmetricExcept<T>(this IEnumerable<T> seq1,
    IEnumerable<T> seq2)
{
    HashSet<T> hashSet = new HashSet<T>(seq1);
    hashSet.SymmetricExceptWith(seq2);
    return hashSet.Select(x => x);
}

6

私はあなたが探していると思うExcept

Except演算子は、2つのシーケンス間のセット差を生成します。最初のシーケンスで、2番目に表示されない要素のみを返します。オプションで、独自の等価比較関数を提供できます。

詳細については、このリンクこのリンク、またはGoogleを確認してください。


2

NonIntersectメソッドが何を行うことになっているのか(集合論に関して)100%わかりません-それは
B \ A(BからAで発生しないものすべて)ですか?
はいの場合、Except操作(B.Except(A))を使用できるはずです。


セットの交差==A∪B\A∩B–
1

2
/// <summary>
/// Given two list, compare and extract differences
/// http://stackoverflow.com/questions/5620266/the-opposite-of-intersect
/// </summary>
public class CompareList
{
    /// <summary>
    /// Returns list of items that are in initial but not in final list.
    /// </summary>
    /// <param name="listA"></param>
    /// <param name="listB"></param>
    /// <returns></returns>
    public static IEnumerable<string> NonIntersect(
        List<string> initial, List<string> final)
    {
        //subtracts the content of initial from final
        //assumes that final.length < initial.length
        return initial.Except(final);
    }

    /// <summary>
    /// Returns the symmetric difference between the two list.
    /// http://en.wikipedia.org/wiki/Symmetric_difference
    /// </summary>
    /// <param name="initial"></param>
    /// <param name="final"></param>
    /// <returns></returns>
    public static IEnumerable<string> SymmetricDifference(
        List<string> initial, List<string> final)
    {
        IEnumerable<string> setA = NonIntersect(final, initial);
        IEnumerable<string> setB = NonIntersect(initial, final);
        // sum and return the two set.
        return setA.Concat(setB);
    }
}

2

array1.NonIntersect(array2);

このような演算子は交差しないため、Linqには存在しません。

例外->ユニオン->例外

a.except(b).union(b.Except(a));

-1
string left = "411329_SOFT_MAC_GREEN";
string right= "SOFT_MAC_GREEN";

string[] l = left.Split('_');
string[] r = right.Split('_');

string[] distinctLeft = l.Distinct().ToArray();
string[] distinctRight = r.Distinct().ToArray();

var commonWord = l.Except(r, StringComparer.OrdinalIgnoreCase)
string result = String.Join("_",commonWord);
result = "411329"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.