[c#] 두 목록의 차이점

CustomsObjects로 채워진 두 개의 일반 목록이 있습니다.

세 번째 목록에서 두 목록 (두 번째 목록의 항목없이 첫 번째 목록에있는 항목)의 차이점을 검색해야합니다.

사용 .Except()하는 것이 좋은 생각이라고 생각했지만 사용 방법을 모르겠습니다 .. 도움말!



답변

사용하는 Except것이 바로 올바른 방법입니다. 만약 당신의 유형 대체 Equals하고 GetHashCode, 또는 당신은 단지 참조 유형 평등에 관심이있는 (즉, 두 개의 참조이다 그들이 동일한 객체를 참조하는 경우에만 “동일”), 당신은 그냥 사용할 수 있습니다 :

var list3 = list1.Except(list2).ToList();

예를 들어 ID로 동일성에 대한 사용자 정의 아이디어를 표현해야하는 경우 IEqualityComparer<T>. 예를 들면 :

public class IdComparer : IEqualityComparer<CustomObject>
{
    public int GetHashCode(CustomObject co)
    {
        if (co == null)
        {
            return 0;
        }
        return co.Id.GetHashCode();
    }

    public bool Equals(CustomObject x1, CustomObject x2)
    {
        if (object.ReferenceEquals(x1, x2))
        {
            return true;
        }
        if (object.ReferenceEquals(x1, null) ||
            object.ReferenceEquals(x2, null))
        {
            return false;
        }
        return x1.Id == x2.Id;
    }
}

그런 다음 다음을 사용하십시오.

var list3 = list1.Except(list2, new IdComparer()).ToList();

이렇게하면 모든 중복 요소가 제거됩니다. 중복을 보존해야하는 경우 list2다음과 같이 집합을 만들고 사용하는 것이 가장 쉬울 것입니다 .

var list3 = list1.Where(x => !set2.Contains(x)).ToList();


답변

다음과 같이 할 수 있습니다.

var result = customlist.Where(p => !otherlist.Any(l => p.someproperty == l.someproperty));


답변

강조하는 것이 중요하다고 생각합니다. Except 메서드 를 사용 하면 두 번째 항목 만 제외하고 첫 번째 항목에있는 항목 만 반환됩니다. 첫 번째에 나타나지 않는 두 번째 요소는 반환하지 않습니다.

var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };

var list3 = list1.Except(list2).ToList(); //list3 contains only 1, 2

그러나 두 목록의 실제 차이를 원한다면 :

두 번째 항목이없는 첫 번째 항목과 첫 번째 항목이없는 두 번째 항목입니다.

Except를 두 번 사용해야합니다.

var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };

var list3 = list1.Except(list2); //list3 contains only 1, 2
var list4 = list2.Except(list1); //list4 contains only 6, 7
var resultList = list3.Concat(list4).ToList(); //resultList contains 1, 2, 6, 7

또는 HashSet의 SymmetricExceptWith 메소드를 사용할 수 있습니다 . 그러나 다음과 같은 세트를 변경합니다.

var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };

var list1Set = list1.ToHashSet(); //.net framework 4.7.2 and .net core 2.0 and above otherwise new HashSet(list1)
list1Set.SymmetricExceptWith(list2);
var resultList = list1Set.ToList(); //resultList contains 1, 2, 6, 7


답변

var third = first.Except(second);

(당신은 또한 호출 할 수 있습니다 ToList()Except()당신이 게으른 컬렉션을 참조하는 마음에 들지 않으면.)

Except()값이 같은베이스 데이터 유형이다 비교되는 경우에있어서, 기본 비교를 사용하여 값을 비교 int, string, decimal

그렇지 않으면 객체 주소로 비교가 이루어집니다. 이는 아마도 원하는 것이 아닐 것입니다 …이 경우 사용자 지정 개체를 구현 IComparable(또는 사용자 지정을 구현 IEqualityComparer하고 Except()메서드에 전달 )합니다.


답변

var list3 = list1.Where(x => !list2.Any(z => z.Id == x.Id)).ToList();

참고 : list3두 목록에없는 항목 또는 개체가 포함됩니다. 참고 : ToList()아닙니다toList()


답변

Except 확장 메서드는 두 개의 IEumerable에서 작동하기 때문에 O (n ^ 2) 작업이 될 것 같습니다. 성능이 문제인 경우 (목록이 큰 경우) list1에서 HashSet을 만들고 HashSet의 ExceptWith 메서드를 사용하는 것이 좋습니다.


답변

내 해결책은 다음과 같습니다.

    List<String> list1 = new List<String>();

    List<String> list2 = new List<String>();

    List<String> exceptValue = new List<String>();

foreach(String L1 in List1)
{
    if(!List2.Contains(L1)
    {
         exceptValue.Add(L1);
    }
}
foreach(String L2 in List2)
{
    if(!List1.Contains(L2)
    {
         exceptValue.Add(L2);
    }
}