순서 무시로 동일한 두 목록 개체 비교
또 하나의 목록 비교 질문입니다.
List<MyType> list1;
List<MyType> list2;
목록 내 위치에 관계없이 둘 다 동일한 요소를 가지고 있는지 확인해야 합니다.각 MyType 개체는 목록에 여러 번 나타날 수 있습니다.이것을 체크하는 기능이 내장되어 있습니까?각 요소가 목록에 한 번만 표시되도록 보장하면 어떻게 됩니까?
편집: 답변 감사합니다만, 제가 뭔가를 추가하는 것을 잊었습니다.각 요소의 발생 횟수는 양쪽 목록에서 동일합니다.
같은 항목(즉, 각 항목의 동일한 수)을 원하는 경우, 비교하기 전에 정렬하는 것이 가장 간단한 해결책이라고 생각합니다.
Enumerable.SequenceEqual(list1.OrderBy(t => t), list2.OrderBy(t => t))
편집:
이 솔루션에서는 퍼포먼스가 약간 향상되고(약 10배 고속),IEquatable
,것은 아니다.IComparable
:
public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2) {
var cnt = new Dictionary<T, int>();
foreach (T s in list1) {
if (cnt.ContainsKey(s)) {
cnt[s]++;
} else {
cnt.Add(s, 1);
}
}
foreach (T s in list2) {
if (cnt.ContainsKey(s)) {
cnt[s]--;
} else {
return false;
}
}
return cnt.Values.All(c => c == 0);
}
편집 2:
임의의 데이터 타입(예를 들어 Frank Tzanabetis가 지적한 null 타입)을 키로 처리하려면 사전의 비교자를 필요로 하는 버전을 작성합니다.
public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer) {
var cnt = new Dictionary<T, int>(comparer);
...
발생 횟수에 구애받지 않으신다면 이렇게 접근하겠습니다.해시 세트를 사용하면 단순 반복보다 성능이 향상됩니다.
var set1 = new HashSet<MyType>(list1);
var set2 = new HashSet<MyType>(list2);
return set1.SetEquals(set2);
이를 위해서는 재지정해야 합니다..GetHashCode()
및 구현IEquatable<MyType>
에MyType
.
쓴대로, 이 질문은 양면성이 있다.스테이트먼트:
목록 내 위치에 관계없이 둘 다 동일한 요소를 가지고 있습니다.각 MyType 개체는 목록에 여러 번 나타날 수 있습니다.
는 2개의 목록에 동일한 오브젝트세트가 있는지, 아니면 동일한 고유 세트가 있는지 여부를 나타내지 않습니다.
컬렉션의 멤버 세트가 순서에 관계없이 완전히 동일한지 확인하려면 다음을 사용합니다.
// lists should have same count of items, and set difference must be empty
var areEquivalent = (list1.Count == list2.Count) && !list1.Except(list2).Any();
두 컬렉션에 동일한 개별 멤버 세트가 있는지 확인하려면(어느 쪽이든 중복이 무시됨) 다음을 사용할 수 있습니다.
// check that [(A-B) Union (B-A)] is empty
var areEquivalent = !list1.Except(list2).Union( list2.Except(list1) ).Any();
설정 조작 사용(Intersect
,Union
,Except
)는 다음과 같은 방법을 사용하는 것보다 효율적입니다.Contains
제 생각에는 당신의 질문에 대한 기대도 더 잘 표현되어 있습니다.
편집: 질문을 명확히 했습니다.복제가 중요하기 때문에 첫 번째 양식을 사용하고 싶다고 말할 수 있습니다.다음은 원하는 결과를 얻을 수 있음을 보여주는 간단한 예입니다.
var a = new[] {1, 2, 3, 4, 4, 3, 1, 1, 2};
var b = new[] { 4, 3, 2, 3, 1, 1, 1, 4, 2 };
// result below should be true, since the two sets are equivalent...
var areEquivalent = (a.Count() == b.Count()) && !a.Except(b).Any();
Guffa의 답변 외에도 이 변형을 사용하여 더 짧은 표기법을 사용할 수 있습니다.
public static bool ScrambledEquals<T>(this IEnumerable<T> list1, IEnumerable<T> list2)
{
var deletedItems = list1.Except(list2).Any();
var newItems = list2.Except(list1).Any();
return !newItems && !deletedItems;
}
이것이 당신이 원하는 것을 할 수 있다고 생각합니다.
list1.All(item => list2.Contains(item)) &&
list2.All(item => list1.Contains(item));
구별하고 싶은 경우는, 다음과 같이 변경할 수 있습니다.
list1.All(item => list2.Contains(item)) &&
list1.Distinct().Count() == list1.Count &&
list1.Count == list2.Count
이것은 조금 어려운 문제로, 「두 개의 리스트가 서로 순열인지 아닌지를 테스트한다」라고 하는 것으로 정리할 수 있습니다.
다른 사람이 제공한 솔루션은 두 목록에 동일한 고유 요소가 포함되어 있는지 여부만 나타내는 것이라고 생각합니다.예를 들어 이것은 필요하지만 불충분한 테스트입니다.{1, 1, 2, 3}
.의 치열이 아니다.{3, 3, 1, 2}
두 계수는 동일하고 동일한 개별 요소를 포함하고 있다.
이 방법이 가장 효율적이지는 않지만 효과가 있을 것이라고 생각합니다.
static bool ArePermutations<T>(IList<T> list1, IList<T> list2)
{
if(list1.Count != list2.Count)
return false;
var l1 = list1.ToLookup(t => t);
var l2 = list2.ToLookup(t => t);
return l1.Count == l2.Count
&& l1.All(group => l2.Contains(group.Key) && l2[group.Key].Count() == group.Count());
}
은 나에게가 있었다:
, 2개의 엔티티에 달라집니다. 를 들어, 에 의존합니다.ID
그에 맞는 세 다음할 수
var list3 = List1.Where(n => !List2.select(n1 => n1.Id).Contains(n.Id));
이 방법을 사용합니다.)
public delegate bool CompareValue<in T1, in T2>(T1 val1, T2 val2);
public static bool CompareTwoArrays<T1, T2>(this IEnumerable<T1> array1, IEnumerable<T2> array2, CompareValue<T1, T2> compareValue)
{
return array1.Select(item1 => array2.Any(item2 => compareValue(item1, item2))).All(search => search)
&& array2.Select(item2 => array1.Any(item1 => compareValue(item1, item2))).All(search => search);
}
이거 먹어봐!!!
다음 코드를 사용하여 하나 이상의 필드를 비교하여 필요에 따라 결과 목록을 생성할 수 있습니다.결과 목록에는 수정된 항목만 포함됩니다.
// veriables been used
List<T> diffList = new List<T>();
List<T> gotResultList = new List<T>();
// compare First field within my MyList
gotResultList = MyList1.Where(a => !MyList2.Any(a1 => a1.MyListTField1 == a.MyListTField1)).ToList().Except(gotResultList.Where(a => !MyList2.Any(a1 => a1.MyListTField1 == a.MyListTField1))).ToList();
// Generate result list
diffList.AddRange(gotResultList);
// compare Second field within my MyList
gotResultList = MyList1.Where(a => !MyList2.Any(a1 => a1.MyListTField2 == a.MyListTField2)).ToList().Except(gotResultList.Where(a => !MyList2.Any(a1 => a1.MyListTField2 == a.MyListTField2))).ToList();
// Generate result list
diffList.AddRange(gotResultList);
MessageBox.Show(diffList.Count.ToString);
언급URL : https://stackoverflow.com/questions/3669970/compare-two-listt-objects-for-equality-ignoring-order
'programing' 카테고리의 다른 글
DataTable을 통해 반복하는 방법 (0) | 2023.04.23 |
---|---|
How do I use an INSERT statement's OUTPUT clause to get the identity value? (0) | 2023.04.23 |
Objective-C에서의 문자열 치환 (0) | 2023.04.23 |
iPhone 앱에서 iOS 7 상태 표시줄을 iOS 6 기본 스타일로 되돌리나요? (0) | 2023.04.23 |
Visual Studio에서 생성된 Windows 서비스 설치 (0) | 2023.04.23 |