Я хотел бы сравнить содержимое нескольких коллекций в моем методе Equals. У меня есть словарь и IList. Есть ли встроенный метод для этого?
Отредактировано: я хочу сравнить два словаря и два ILists, поэтому я думаю, что означает равенство, ясно - если два словаря содержат одинаковые ключи, сопоставленные с одинаковыми значениями, то они равны.
c#
.net
collections
TimK
источник
источник
IList
? Вопрос неоднозначный.Enumerable.SequenceEqual
иISet.SetEquals
предоставить версии этой функциональности. Если вы хотите быть независимыми от заказов и работать с коллекциями, в которых есть дубликаты, вам нужно создать свою собственную. Проверьте реализацию, предложенную в этом постеОтветы:
Enumerable.SequenceEqual
Вы не можете напрямую сравнить список и словарь, но вы можете сравнить список значений из словаря со списком
источник
.Keys
и.Values
может вернуть ключи и значения в любом порядке , они чувствуют , как и этот порядок может измениться , как словарь модифицируется , а также. Я предлагаю вам прочитать, что такое словарь, а что нет.Как и предполагали другие,
SequenceEqual
чувствителен к порядку. Чтобы решить эту проблему, вы можете отсортировать словарь по ключу (который уникален и, следовательно, сортировка всегда стабильна), а затем использоватьSequenceEqual
. Следующее выражение проверяет, равны ли два словаря независимо от их внутреннего порядка:РЕДАКТИРОВАТЬ: Как указал Джепп Стиг Нильсен, некоторые объекты имеют
IComparer<T>
несовместимые с нимиIEqualityComparer<T>
, что приводит к неправильным результатам. При использовании ключей с таким объектом вы должны указать правильное значениеIComparer<T>
для этих ключей. Например, со строковыми ключами (которые показывают эту проблему), вы должны сделать следующее, чтобы получить правильные результаты:источник
CompareTo
? Ваше решение взорвется тогда. А что если тип ключа имеет компаратор по умолчанию, который несовместим с компаратором равенства по умолчанию? Это делоstring
, вы знаете. Например, эти словари (с неявными компараторами равенства по умолчанию) не пройдут ваш тест (под всеми известными мне культурами):var dictionary1 = new Dictionary<string, int> { { "Strasse", 10 }, { "Straße", 20 }, }; var dictionary2 = new Dictionary<string, int> { { "Straße", 20 }, { "Strasse", 10 }, };
IComparer
иIEqualityComparer
- я не знал об этой проблеме, очень интересно! Я обновил ответ с возможным решением. ЧтоCompareTo
касается отсутствия , я думаю, что разработчик должен убедиться, что делегат, предоставленныйOrderBy()
методу, возвращает что-то сопоставимое. Я думаю, что это верно для любого использования илиOrderBy()
даже вне словарных сравнений.В дополнение к упомянутому SequenceEqual , который
(который может быть компаратором по умолчанию, то есть переопределением
Equals()
)Стоит отметить, что в .Net4 есть SetEquals для
ISet
объектов, которыеПоэтому, если вы хотите иметь список объектов, но они не обязательно должны быть в определенном порядке, подумайте, что
ISet
(например, aHashSet
) может быть правильным выбором.источник
Взгляните на метод Enumerable.SequenceEqual
источник
.NET Отсутствует какие-либо мощные инструменты для сравнения коллекций. Я разработал простое решение, которое вы можете найти по ссылке ниже:
http://robertbouillon.com/2010/04/29/comparing-collections-in-net/
Это выполнит сравнение на равенство независимо от порядка:
Это проверит, были ли элементы добавлены / удалены:
Это увидит, какие элементы в словаре изменились:
источник
.Removed
так же, какlist1.Except(list2)
,.Added
естьlist2.Except(list1)
,.Equal
естьlist1.Intersect(list2)
и.Different
естьoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => left.Value == right.Value)
. Вы можете сделать практически любое сравнение с LINQ..Different
естьoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => new { Key = left.Key, NewValue = right.Value, Different = left.Value == right.Value).Where(d => d.Different)
. И вы можете даже добавить,OldValue = left.Value
если вам нужно старое значение тоже.Я не знал о методе Enumerable.SequenceEqual (вы чему-то учитесь каждый день ....), но я собирался предложить использовать метод расширения; что-то вроде этого:
Интересно, что после 2 секунд чтения SequenceEqual похоже, что Microsoft создала функцию, которую я описал для вас.
источник
Это не является прямым ответом на ваши вопросы, но MS TestTools и NUnit предоставляют
который делает в значительной степени то, что вы хотите.
источник
Для сравнения коллекций вы также можете использовать LINQ.
Enumerable.Intersect
возвращает все пары, которые равны Вы можете сравнить два словаря, как это:Первое сравнение необходимо, потому что
dict2
может содержать все ключиdict1
и многое другое.Вы можете также использовать думать о вариантах с использованием
Enumerable.Except
иEnumerable.Union
которые приводят к подобным результатам. Но может использоваться для определения точных различий между наборами.источник
Как насчет этого примера:
Предоставлено: https://www.dotnetperls.com/dictionary-equals
источник
Для упорядоченных коллекций (List, Array) используйте
SequenceEqual
для использования HashSet
SetEquals
Для словаря вы можете сделать:
(Более оптимизированное решение будет использовать сортировку, но для этого потребуется
IComparable<TValue>
)источник
Нет. В основе коллекции нет понятия равенства. Если вы думаете об этом, нет никакого способа сравнить коллекции, которые не являются субъективными. Например, сравнивая ваш IList с вашим словарем, будут ли они равны, если все ключи были в IList, все значения были в IList или оба были в IList? Не существует очевидного способа сравнения этих двух коллекций без знания того, для чего они будут использоваться, поэтому метод равных общего назначения не имеет смысла.
источник
Нет, потому что фреймворк не знает, как сравнивать содержимое ваших списков.
Посмотри на это:
http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx
источник
IComparer<T>
, Перекрываяobject.Equals
,IEquatable<T>
,IComparable<T>
...источник
Не было, нет и не может быть, по крайней мере, я бы поверил в это. Причина заключается в том, что равенство коллекций, вероятно, определяется пользователем.
Элементы в коллекциях не должны быть в определенном порядке, хотя они имеют естественный порядок, это не то, на что должны опираться алгоритмы сравнения. Скажем, у вас есть две коллекции:
Они равны или нет? Вы должны знать, но я не знаю, какова ваша точка зрения.
Коллекции концептуально неупорядочены по умолчанию, пока алгоритмы не предоставят правила сортировки. То же самое, что SQL-сервер предлагает вашему вниманию, когда вы пытаетесь сделать нумерацию страниц, вам необходимо предоставить правила сортировки:
https://docs.microsoft.com/en-US/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017
Еще две коллекции:
Опять они равны или нет? Кому ты рассказываешь ..
Повторяемость элементов коллекции играет свою роль в различных сценариях, и некоторые коллекции, например
Dictionary<TKey, TValue>
, даже не допускают повторения элементов.Я полагаю, что эти виды равенства определяются приложением, и поэтому структура не обеспечивает всех возможных реализаций.
Ну, в общем случае
Enumerable.SequenceEqual
это достаточно хорошо, но возвращает false в следующем случае:Я прочитал некоторые ответы на такие вопросы (вы можете Google для них) и что бы я использовал, в целом:
Это означает, что одна коллекция представляет другую в своих элементах, включая повторяющиеся моменты времени без учета первоначального порядка. Некоторые замечания о реализации:
GetHashCode()
только для заказа, а не для равенства; Я думаю, что в этом случае достаточноCount()
на самом деле не будет перечислять коллекцию и напрямую попадет в свойство реализацииICollection<T>.Count
Если ссылки равны, это просто Борис
источник