컬렉션을 비교하는 기본 제공 방법이 있습니까?
내 Equals 방법에서 두 컬렉션의 내용을 비교하고 싶습니다. 사전과 IList가 있습니다. 이 작업을 수행하는 기본 제공 방법이 있습니까?
편집 : 두 개의 사전과 두 개의 IList를 비교하고 싶기 때문에 평등의 의미가 분명하다고 생각합니다. 두 사전에 동일한 값에 매핑 된 동일한 키가 포함되어 있으면 동일합니다.
지정된 IEqualityComparer (T)를 사용하여 요소를 비교하여 두 시퀀스가 같은지 확인합니다.
목록과 사전을 직접 비교할 수는 없지만 사전의 값 목록을 목록과 비교할 수는 있습니다.
다른 사람들이 제안하고 언급했듯이 SequenceEqual
순서에 민감합니다. 이를 해결하기 위해 키를 기준으로 사전을 정렬하고 (고유하므로 정렬은 항상 안정적 임)를 사용하십시오 SequenceEqual
. 다음 표현식은 내부 순서와 상관없이 두 사전이 동일한 지 확인합니다.
dictionary1.OrderBy(kvp => kvp.Key).SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key))
편집 : Jeppe Stig Nielsen이 지적한 것처럼 일부 객체에는와 IComparer<T>
호환되지 않는 객체가있어 IEqualityComparer<T>
잘못된 결과를 생성합니다. 이러한 객체와 함께 키를 사용하는 경우 IComparer<T>
해당 키에 올바른 키를 지정해야 합니다. 예를 들어,이 문제를 나타내는 문자열 키를 사용하면 올바른 결과를 얻으려면 다음을 수행해야합니다.
dictionary1.OrderBy(kvp => kvp.Key, StringComparer.Ordinal).SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key, StringComparer.Ordinal))
언급 한 외에 SequenceEqual 어느
두 목록의 길이가 같고 해당 요소가 비교 자에 따라 동일하게 비교되는 경우 true
(기본 비교기, 즉 overriden 일 수 있음 Equals()
)
.Net4 에는 ISet
객체에 SetEquals 가 있음을 언급 할 가치가 있습니다.
요소 및 중복 요소의 순서를 무시합니다.
따라서 객체 목록을 원하지만 특정 순서로 정렬 할 필요는없는 경우 ISet
(와 같은 HashSet
)가 올바른 선택 일 수 있습니다.
Enumerable.SequenceEqual 메소드를 살펴보십시오.
var dictionary = new Dictionary<int, string>() {{1, "a"}, {2, "b"}};
var intList = new List<int> {1, 2};
var stringList = new List<string> {"a", "b"};
var test1 = dictionary.Keys.SequenceEqual(intList);
var test2 = dictionary.Values.SequenceEqual(stringList);
.NET 모음을 비교할 수있는 강력한 도구가 없습니다. 아래 링크에서 찾을 수있는 간단한 솔루션을 개발했습니다.
http://robertbouillon.com/2010/04/29/comparing-collections-in-net/
순서에 관계없이 평등 비교를 수행합니다.
var list1 = new[] { "Bill", "Bob", "Sally" };
var list2 = new[] { "Bob", "Bill", "Sally" };
bool isequal = list1.Compare(list2).IsSame;
항목이 추가 / 제거되었는지 확인합니다.
var list1 = new[] { "Billy", "Bob" };
var list2 = new[] { "Bob", "Sally" };
var diff = list1.Compare(list2);
var onlyinlist1 = diff.Removed; //Billy
var onlyinlist2 = diff.Added; //Sally
var inbothlists = diff.Equal; //Bob
사전의 어떤 항목이 변경되었는지 확인할 수 있습니다.
var original = new Dictionary<int, string>() { { 1, "a" }, { 2, "b" } };
var changed = new Dictionary<int, string>() { { 1, "aaa" }, { 2, "b" } };
var diff = original.Compare(changed, (x, y) => x.Value == y.Value, (x, y) => x.Value == y.Value);
foreach (var item in diff.Different)
Console.Write("{0} changed to {1}", item.Key.Value, item.Value.Value);
//Will output: a changed to aaa
Enumerable.SequenceEqual 메소드 (매일 무언가를 배우고 있습니다 ...)에 대해 몰랐지만 확장 메소드를 사용하는 것이 좋습니다. 이 같은:
public static bool IsEqual(this List<int> InternalList, List<int> ExternalList)
{
if (InternalList.Count != ExternalList.Count)
{
return false;
}
else
{
for (int i = 0; i < InternalList.Count; i++)
{
if (InternalList[i] != ExternalList[i])
return false;
}
}
return true;
}
흥미롭게도 SequenceEqual에 대해 2 초가 걸린 후에 Microsoft가 내가 설명한 기능을 구축 한 것 같습니다.
이것은 귀하의 질문에 직접 대답하지는 않지만 MS의 TestTools와 NUnit은
CollectionAssert.AreEquivalent
그것은 당신이 원하는 것을 거의 수행합니다.
컬렉션을 비교하기 위해 LINQ를 사용할 수도 있습니다. Enumerable.Intersect
동일한 모든 쌍을 반환합니다. 다음과 같이 두 사전을 비교할 수 있습니다.
(dict1.Count == dict2.Count) && dict1.Intersect(dict2).Count() == dict1.Count
The first comparison is needed because dict2
can contain all the keys from dict1
and more.
You can also use think of variations using Enumerable.Except
and Enumerable.Union
that lead to similar results. But can be used to determine the exact differences between sets.
How about this example:
static void Main()
{
// Create a dictionary and add several elements to it.
var dict = new Dictionary<string, int>();
dict.Add("cat", 2);
dict.Add("dog", 3);
dict.Add("x", 4);
// Create another dictionary.
var dict2 = new Dictionary<string, int>();
dict2.Add("cat", 2);
dict2.Add("dog", 3);
dict2.Add("x", 4);
// Test for equality.
bool equal = false;
if (dict.Count == dict2.Count) // Require equal count.
{
equal = true;
foreach (var pair in dict)
{
int value;
if (dict2.TryGetValue(pair.Key, out value))
{
// Require value be equal.
if (value != pair.Value)
{
equal = false;
break;
}
}
else
{
// Require key be present.
equal = false;
break;
}
}
}
Console.WriteLine(equal);
}
Courtesy : https://www.dotnetperls.com/dictionary-equals
For ordered collections (List, Array) use SequenceEqual
for HashSet use SetEquals
for Dictionary you can do:
namespace System.Collections.Generic {
public static class ExtensionMethods {
public static bool DictionaryEquals<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> d1, IReadOnlyDictionary<TKey, TValue> d2) {
if (object.ReferenceEquals(d1, d2)) return true;
if (d2 is null || d1.Count != d2.Count) return false;
foreach (var (d1key, d1value) in d1) {
if (!d2.TryGetValue(d1key, out TValue d2value)) return false;
if (!d1value.Equals(d2value)) return false;
}
return true;
}
}
}
(A more optimized solution will use sorting but that will require IComparable<TValue>
)
No. The collection framework doesn't have any concept of equality. If you think about it there is no way of comparing collections which isn't subjective. For instance comparing your IList to your Dictionary, would they be equal if all the keys were in the IList, all the values were in the IList or if both were in the IList? There is no obvious way of comparing these two collections without knowledge of what they are to be used for so a general purpose equals method makes no sense.
No, because the framework doesn't know how to compare the contents of your lists.
Have a look at this:
http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx
public bool CompareStringLists(List<string> list1, List<string> list2)
{
if (list1.Count != list2.Count) return false;
foreach(string item in list1)
{
if (!list2.Contains(item)) return false;
}
return true;
}
There wasn't, isn't and might not be, at least I would believe so. The reason behind is collection equality is probably an user defined behavior.
Elements in collections are not supposed to be in a particular order though they do have an ordering naturally, it's not what the comparing algorithms should rely on. Say you have two collections of:
{1, 2, 3, 4}
{4, 3, 2, 1}
Are they equal or not? You must know but I don't know what's your point of view.
Collections are conceptually unordered by default, until the algorithms provide the sorting rules. The same thing SQL server will bring to your attention is when you trying to do pagination, it requires you to provide sorting rules:
Yet another two collections:
{1, 2, 3, 4}
{1, 1, 1, 2, 2, 3, 4}
Again, are they equal or not? You tell me ..
Element repeatability of a collection plays its role in different scenarios and some collections like Dictionary<TKey, TValue>
don't even allow repeated elements.
I believe these kinds of equality are application defined and the framework therefore did not provide all of the possible implementations.
Well, in general cases Enumerable.SequenceEqual
is good enough but it returns false in the following case:
var a = new Dictionary<String, int> { { "2", 2 }, { "1", 1 }, };
var b = new Dictionary<String, int> { { "1", 1 }, { "2", 2 }, };
Debug.Print("{0}", a.SequenceEqual(b)); // false
I read some answers to questions like this(you may google for them) and what I would use, in general:
public static class CollectionExtensions {
public static bool Represents<T>(this IEnumerable<T> first, IEnumerable<T> second) {
if(object.ReferenceEquals(first, second)) {
return true;
}
if(first is IOrderedEnumerable<T> && second is IOrderedEnumerable<T>) {
return Enumerable.SequenceEqual(first, second);
}
if(first is ICollection<T> && second is ICollection<T>) {
if(first.Count()!=second.Count()) {
return false;
}
}
first=first.OrderBy(x => x.GetHashCode());
second=second.OrderBy(x => x.GetHashCode());
return CollectionExtensions.Represents(first, second);
}
}
That means one collection represents the other in their elements including repeated times without taking the original ordering into account. Some notes of the implementation:
GetHashCode()
is just for the ordering not for equality; I think it's enough in this caseCount()
will not really enumerates the collection and directly fall into the property implementation ofICollection<T>.Count
If the references are equal, it's just Boris
참고URL : https://stackoverflow.com/questions/43500/is-there-a-built-in-method-to-compare-collections
'Programing' 카테고리의 다른 글
Eclipse의 기존 소스에서 프로젝트를 작성하고 찾는 방법은 무엇입니까? (0) | 2020.05.27 |
---|---|
brk () 시스템 호출은 무엇을합니까? (0) | 2020.05.27 |
TypeScript에서 추상 메서드 선언 (0) | 2020.05.27 |
쉘 기능을 어떻게 삭제합니까? (0) | 2020.05.27 |
스레드를 만드는 데 비용이 많이 드는 이유는 무엇입니까? (0) | 2020.05.27 |