교차 ()의 반대


276

교차는 다음과 같이 두 컬렉션 간의 일치 항목을 찾는 데 사용할 수 있습니다.

// 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
4를 출력으로 원하는지 확인하십시오. 또는 1과 4
Øyvind Bråthen

@ oyvind-knobloch-brathen 예, 저는 4 만 원합니다
Peter Bridger

23
참고로이 유형의 집합을 대칭 차이 라고합니다 .
Mike T

19
기술적으로 말하면 대칭 차이는 [1, 4]가됩니다. Peter는 array1에없는 (즉, 4) array2의 요소 만 원했기 때문에 상대 보완 (일명 Set-Theoretic Difference)
rtorres

답변:


377

언급했듯이 결과로 4를 얻으려면 다음과 같이하십시오.

var nonintersect = array2.Except(array1);

실제 비 교차로를 원한다면 (1과 4 모두) 트릭을 수행해야합니다.

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

이것은 가장 성능이 좋은 솔루션은 아니지만 작은 목록의 경우 제대로 작동합니다.


2
더 나은 성능의 솔루션은 무엇입니까? 감사!
shanabus

6
두 개의 중첩 된 for 루프를 사용하여 더 빠르게 수행 할 수 있지만 코드는 이보다 더 복잡합니다. 이것에 대한 가독성을 세어 볼 때, 나는 매우 쉽게 읽을 수 있으므로이 변형을 분명히 사용할 것입니다.
Øyvind Brå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

이것이 더 잘 수행됩니까? array1.AddRange (배열 2. 제외 (배열 1));
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
실제 응용 프로그램에서 두 개를 비교 한 결과 각 문자열에 약 125 개의 문자열 목록이 있습니다. 첫 번째 접근법을 사용하는 것은 실제로 해당 크기의 목록에 대해 더 빠르지 만, 반 밀리 초 미만인 두 가지 접근법에서는 거의 중요하지 않습니다.
Dan

1
BCL에 Linq 확장 방법이 있다면 좋을 것입니다. 누락 된 것 같습니다.
Drew Noakes

누군가가 SymmetricExceptWith를 벤치마킹하고 훨씬 더 빨리 발견 skylark-software.com/2011/07/linq-and-set-notation.html
콜린

11

이 코드는 각 시퀀스를 한 번만 열거 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:

제외 연산자는 두 시퀀스 사이에 설정된 차이를 생성합니다. 첫 번째 시퀀스에서는 두 번째에는 나타나지 않는 요소 만 반환합니다. 선택적으로 고유 한 동등 비교 기능을 제공 할 수 있습니다.

체크 아웃 이 링크 , 링크 자세한 내용은, 또는 Google을.


2

NonIntersect 메소드가 무엇을 해야하는지 100 % 확신하지 못합니다 (세트 이론과 관련하여)
-B \ A (B에서 A에서 발생하지 않는 모든 것)입니까?
그렇다면 Except 연산 (B.Except (A))을 사용할 수 있어야합니다.


집합의 교차점 == A∪B \ A∩B
amuliar

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 (배열 2);

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.