Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/34: Рейтинг темы: голосов - 34, средняя оценка - 4.62
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
.NET 4.x

Быстрое сравнение коллекций

18.05.2017, 23:16. Показов 7413. Ответов 27
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть 2 коллекции List<SomeItem>.
Одна исходная, с другой работаю. Каким образом можно в коде (к примеру по какому либо моему событию) проверить идентичность коллекций?
Айтемов в коллекции штук по 20, а вот свойств у них у каждой море. Т.е. если сравнивать свойства поименно, то будет ооочень много кода.

Добавлено через 6 минут
Вот по быстрому накидал классов для примера.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SomeItem()
{
   public string Name {get;set;}
   public PaintData PaintData {get;set;}
   public PaintBank PaintBank{get;set;}
}
 
public class PaintData()
{
   public string PaintName {get;set;}
   public EColor ColorType {get;set;}
}
 
public class PaintBank()
{
   public string BankName{get;set;}
   public double Count {get;set;}
}
Добавлено через 1 минуту
А так, есть и вычисляемые свойства, и составные, и Object (который правда по большей части null)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
18.05.2017, 23:16
Ответы с готовыми решениями:

Сравнение коллекций
есть кулинарная книга. в которой нужно сделать поиск по рецептам(пользователь вводит неизвестное заранее количество ингридиентов) затем...

Как долго будет выполняться сравнение коллекций?
Добрый день! Суть программы такая. Отправляется запрос на сайт, ответ приходит в виде JSON, в котором содержится 100 последних действий,...

Сравнение коллекций по столбцам
Здравствуйте. У меня два распарсенных файла, занесенных в коллекции atomList.Add(at) и atomList2.Add(atn). В каждой коллекции...

27
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
19.05.2017, 01:25
skilllab, 1) реализовать IEquitable для этих интерфейсов, либо сделать компарер IEqualityComparer для той же цели
- зависит от того, являются ли объекты сравниваемыми сами по себе, тогда реализовываем, либо нам нужно посравнивать в контексте - тогда компарер сбоку.
2) заюзать col1.SequenceEquals(col2) из LINQ и радоваться жизни.

Если нужно сравнивать без учета порядка элементов, то все сложнее. Хотя первый пункт в любом случае нужен.
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
19.05.2017, 08:27  [ТС]
Я так понял погуглил, что второе следует из первого?
А может что-то unmanaged задействовать? Типа чтения памяти, размера... ещё чего то.

Смысл всего действа - это что-то вроде метки IsDirty для дальнейшего сохранения. Типа раз коллекция не изменилась, то и сохранять нечего. Причем, если изменил, к примеру, BankName на одно, а потом вернул старое - то метка изменения сигналит = всё ок, изменений с исходной нет.

Добавлено через 1 минуту
Цитата Сообщение от Psilon Посмотреть сообщение
являются ли объекты сравниваемыми сами по себе
Всегда да. Без исключений. Исключения будут разве что при битой памяти.

Добавлено через 8 минут
Цитата Сообщение от Psilon Посмотреть сообщение
Если нужно сравнивать без учета порядка элементов
вот этого не понял.

Может ещё что сможет натолкнуть на мысль:
- у каждого айтема есть уникальное свойство. Вторая коллекция изначально, это отражение первой. (возможно это решение вопроса об порядке элементов, можно сравнивать поиском по этому свойству)
- коллекция может изменяться как по полям, так и по количеству. Но, если изначально было 3 элемента, потом один удалили и добавили новый, то это уже изменённая коллекция. Оно то итак понятно

Добавлено через 10 минут
Цитата Сообщение от Psilon Посмотреть сообщение
IEquitable
Правильно ли я понял, что IEequatable это расширение IComparable? И лучше уж тогда прям IComparable реализовывать. Чтоб потом в коде можно было с коллекциями на выборку работать. А к нему ещё EqualityComparer Ухх сколько писанины намечается
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
19.05.2017, 08:49
Цитата Сообщение от Psilon Посмотреть сообщение
1) реализовать IEquitable для этих интерфейсов, либо сделать компарер IEqualityComparer для той же цели
- зависит от того, являются ли объекты сравниваемыми сами по себе, тогда реализовываем, либо нам нужно посравнивать в контексте - тогда компарер сбоку.
А какую проблему автора это решает? Как я понял проблема либо в том, что придется писать много кода, поскольку много разных классов, либо в том, что низкая скорость сравнения.
Цитата Сообщение от skilllab Посмотреть сообщение
Смысл всего действа - это что-то вроде метки IsDirty для дальнейшего сохранения. Типа раз коллекция не изменилась, то и сохранять нечего. Причем, если изменил, к примеру, BankName на одно, а потом вернул старое - то метка изменения сигналит = всё ок, изменений с исходной нет.
Самое простое решение - слделать объекты сериализуемыми, сделать бинарную сериализацию обоих коллекций в массив byte[] (для исходной это можно сделать только один раз) и потом просто сравнить поэлементно эти массивы. Если массивы равны - значит коллекции идентичны. Как для флажка IsDirty это вполне хорошее и быстрое решение.
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
19.05.2017, 09:20  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Если массивы равны - значит коллекции идентичны
Во! Попробую. Спасибо.

Добавлено через 2 минуты
Цитата Сообщение от Storm23 Посмотреть сообщение
слделать объекты сериализуемыми
Или это тоже "Во!" ибо объекты ж сохраняются, они у меня JSON. А дальше это легко гуглится.
0
Эксперт .NET
 Аватар для Usaga
14087 / 9305 / 1348
Регистрация: 21.01.2016
Сообщений: 34,949
19.05.2017, 09:21
Цитата Сообщение от Storm23 Посмотреть сообщение
Самое простое решение - слделать объекты сериализуемыми, сделать бинарную сериализацию обоих коллекций в массив byte[] (для исходной это можно сделать только один раз) и потом просто сравнить поэлементно эти массивы. Если массивы равны - значит коллекции идентичны. Как для флажка IsDirty это вполне хорошее и быстрое решение.
Ёлы-палы! Нельзя же так жестить.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
19.05.2017, 10:00  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Если массивы равны - значит коллекции идентичны
Тут коллега посоветовал (если делать в таком ручье) не массивы сравнивать, а сумму байт. И тогда порядок точно будет не важен.
0
Эксперт .NET
 Аватар для Usaga
14087 / 9305 / 1348
Регистрация: 21.01.2016
Сообщений: 34,949
19.05.2017, 10:08
skilllab, это нечто отдалённо похожее на контрольную сумму. Не очень надёжный подход, как вы понимаете.

А в чём, собственно сложность описать сравнение всех свойств? Так долго?
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
19.05.2017, 11:18  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
сложность
Дык нет её. Я парень простой ))) раз посоветовали IEquatable, сижу и реализовываю. Раз сказали сравнивать сериализованные массивы, сижу сверяю.
А потооооом уже буду ныть про скорость если на OnCollectionChanged всё это повешу и вся форма будет морозиться на сверке.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
19.05.2017, 11:52
Если гнаться за циферками производительности, то последовательное сравнение свойств объектов класса будет быстрее (особенно, если повезёт и различие выявится в первом-же свойстве). Но этот путь требует целых портянок кода и ниразу не универсален (если не прибегать к рефлексии, но для меня это всё ещё чёрная магия), особенно, если будет несколько сравниваемых типов классов.
Сериализация с последующим побайтным сравнением выглядит максимально эффективным подходом, особенно, если нет требований к криптостойкости и можно возвращать условный FALSE при первом же несовпадении.
Расчитывать ХЭШи и их сравнивать лично я особого смысла не вижу, это лишняя работа, опять-же, если нет требований к криптостойкости процесса в котором эта задача появилась.
0
Эксперт .NET
 Аватар для Usaga
14087 / 9305 / 1348
Регистрация: 21.01.2016
Сообщений: 34,949
19.05.2017, 11:59
Цитата Сообщение от aquaMakc Посмотреть сообщение
Сериализация с последующим побайтным сравнением выглядит максимально эффективным подходом
Ну вот ни разу. Вы заставляете машину делать КУЧУ ненужной работы по выделению памяти и сериализации кучки объектов только ради того, чтобы сэкономить некоторое количество строк кода. Это как использовать String.Split() для подсчёта слов в строке. Ровно тоже самое.

И да, рефлексия ниразу не про производительность.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
19.05.2017, 12:04
Цитата Сообщение от Usaga Посмотреть сообщение
Вы заставляете машину делать КУЧУ ненужной работы по выделению памяти и сериализации кучки объектов
)) вот прям таки КУЧУ? Ужас то какой.
У представим, что у человека класс состоит из 100500 свойств, половина из которых - динамические коллекции. Или у него несколько различных классов тоже не самых простых. Для каждого придётся хардкодить портяну ифов и переборов. Для коллекций, конечно можно использовать LINQ сравнение, но, это ещё больше затормозит сравнение, т.к. банальный for работает быстрее.
0
Эксперт .NET
 Аватар для Usaga
14087 / 9305 / 1348
Регистрация: 21.01.2016
Сообщений: 34,949
19.05.2017, 12:11
aquaMakc, да, придётся "хардкодить". А вы как хотели? Вам кто-то обещал, что всё всегда будет как по маслу?

Цитата Сообщение от aquaMakc Посмотреть сообщение
)) вот прям таки КУЧУ? Ужас то какой.
Да, кучу. Намного больше, чем ничего (а именно столько нужно сериализации и памяти для сравнения двух коллекций).
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
19.05.2017, 12:49
Цитата Сообщение от Usaga Посмотреть сообщение
Да, кучу. Намного больше, чем ничего (а именно столько нужно сериализации и памяти для сравнения двух коллекций).
Ну выделится память на стеке в методе сравнения. Она тихо и мирно издохнет при выходе из метода. Зато метод будет универсален и не в сотни строк, а с десяток максимум.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
19.05.2017, 13:00  [ТС]
Цитата Сообщение от aquaMakc Посмотреть сообщение
класс состоит из 100500 свойств
Нее))) ну не такой уж я и быдлокодер
Цитата Сообщение от aquaMakc Посмотреть сообщение
Для каждого придётся хардкодить портяну ифов
Ну, собсна, после гугла с Equality я и полез на форум за советом. Чтоб не "портянить" особо много. (если, конечно, портяна - это один из лучших правильных вариантов, то да)
Цитата Сообщение от Usaga Посмотреть сообщение
Вы заставляете машину делать КУЧУ ненужной работы по выделению памяти и сериализации кучки объектов
Чем вам она так не угодила то?
http://stackoverflow.com/quest... on-objects
там кода на 10 строк, и всё понятно что происходит.
Я сейчас не за и против сравниваю, ибо попробую оба метода, прост...интересуюсь. Чем сериализованная коллекция хуже моря ифов в классах и подклассах и подклассах и под...
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
19.05.2017, 13:12
Цитата Сообщение от skilllab Посмотреть сообщение
моря ифов в классах и подклассах и подклассах и под...
не, не так. Один метод сравнения, в который передаётся 2 экземпляра класса.
Допустим у вас класс из 3-х свойств типа int и 1 коллекции List<T>
Тогда по варианту посвойственного сравнения вы пишете
C#
1
2
3
4
5
6
7
if (obj1.intProperty1 != obj2.intProperty1)
   return false;
...
if (!obj1.ListProperty1.SequenceEqual(obj2.ListProperty1)
   return false;
...
return true;
По варианту сериализации алгоритм такой:
1) Сериализуете оба объекта в массив байт;
2) Сравниваете длины массивов, если неравны - объекты разные
3) Если равны начинается побайтовое сравнение
4) Если встречается первое же несовпадение - объекты не равны.
5) Если перебрали все байты и они все равны - объекты одинаковы.

Добавлено через 4 минуты
skilllab, в дополнение к первому варианту. Если у вас сравниваемые классы содержат другие классы, то для них надо будет писать отдельные методы сравнения... Так-что, да, ифов в итоге будет много.
1
Эксперт .NET
 Аватар для Usaga
14087 / 9305 / 1348
Регистрация: 21.01.2016
Сообщений: 34,949
19.05.2017, 13:18
skilllab, я не против сериализации. Я против её... своеобразного применения. Я понимаю, что код не должно делать максимально громоздким ради одной производительности и потому, что так "правильно". Хотите, пробуйте, но я бы так делать точно не стал.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
19.05.2017, 13:36  [ТС]
Цитата Сообщение от aquaMakc Посмотреть сообщение
классы содержат другие классы
я в первом сообщении привёл же типа-пример.

Добавлено через 5 минут
Цитата Сообщение от aquaMakc Посмотреть сообщение
Один метод сравнения
это уже получается просто статичный метод? Типа утилитарный.
Передаём 2 коллекции, ищем 2 одинаковых класса по уникальному свойству. Не находим - кидаем флаг. Находим - лезем вглубь, и ещё в глубь и ещё . Хмм...типа недоEquality такой. Будет просто один метод с кучкой ифов. Тож вариант кстати.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
19.05.2017, 13:42
Цитата Сообщение от Storm23 Посмотреть сообщение
А какую проблему автора это решает? Как я понял проблема либо в том, что придется писать много кода, поскольку много разных классов, либо в том, что низкая скорость сравнения.
У автора вроде 2 или 3 класса. Если уж совсем лень (и нет иерархии), можно сделать структуры и заюзать дефолтный слоупочный сравниватель структур. Скорость сравнения будет выше, чем сериализовывать всё и сравнивать побайтово.
skilllab, ансейф тут не поможет, потому что есть строка. А строки "hello" и "hello", насмотря на одинаковое содержимое, находятся по разным адресам в памяти, и при битовом сравнении вернут false. Это можно обойти, если использовать интернирование (тогда все строки с одинаковым содержимым будут и ссылочно одинаковы), тогда можно будет тупо кусками сравнивать по 4-8 байт, в SIMD вообще 512-битные регистры можно заюзать (Гольдшейн так оптимизировал string.Contains). Но это совсем уже упарываться надо, для таких решений нужно бенчмаркать и иметь обоснование, что текущее решение не удовлетворяет по скорости.
Цитата Сообщение от skilllab Посмотреть сообщение
вот этого не понял.
Равны ли коллекции [1,2,3] и [2,1,3]? Без учета порядка - да, с его учетом - нет.
Цитата Сообщение от skilllab Посмотреть сообщение
Смысл всего действа - это что-то вроде метки IsDirty для дальнейшего сохранения. Типа раз коллекция не изменилась, то и сохранять нечего. Причем, если изменил, к примеру, BankName на одно, а потом вернул старое - то метка изменения сигналит = всё ок, изменений с исходной нет.
Делаете коллекцию, трекаете изменения. Например было имя А. Мы поменяли его на Б. Смотрим в словарик изменений, там пусто. Окей, меняем, в словарик добавляем "изменили имя на Б". Потом меняем на С. Смотрим в словарик - там единственная запись "изменили имя на Б". Ок, заменяем это на "изменили имя на С". Потом меняем обратно на А. Смотрим в словарик - там единственная запись "изменили имя на А". Смотрим, что это исходное значение, удаляем запись из словарика. Получаем исходную коллекцию без изменений. Флагом IsDirty будет changesDictionary.Count > 0.

Таким образом, в общем случае это будет выглядеть так: При внесении каких-либо изменений мы смотрим, совпадает ли свойство с исходным. Если нет, то добавляем (или заменяем) в словарике запись "изменили на Х". Если совпадает, то удаляем, если оно было в словарике (вернули в исходное состояние). Чтобы это работало правильно, объекты должны быть неизменяемыми (иначе будет возможность изменить свойство минуя нашу крутую трекинговую коллекцию).

Этот подход хорошо работает, когда объектов - много, а изменений относительно мало.

Ваш подход хорошо работает, когда изменений много, а объектов мало. И он проще в реализации.
Цитата Сообщение от skilllab Посмотреть сообщение
Правильно ли я понял, что IEequatable это расширение IComparable? И лучше уж тогда прям IComparable реализовывать. Чтоб потом в коде можно было с коллекциями на выборку работать. А к нему ещё EqualityComparer Ухх сколько писанины намечается
Нет, это разные вещи, хотя на основе IComparable можно было бы вывести всё остальное, но шарп этого не делает (а жаль, см #9).
Цитата Сообщение от Usaga Посмотреть сообщение
это нечто отдалённо похожее на контрольную сумму. Не очень надёжный подход, как вы понимаете.
Вероятность коллизии SHA512 ниже, чем у гуида, так что в принципе ок. Вопрсо только, что у человека сравнение медленное, а он хочет по не самому быстрому алгоритму хэши считать
skilllab, если нужен перфоманс, то сериализация и последующие сравнения явно не то, что вы хотите. Это Fast & Dirty решение, которое экономит строчки кода за счет скорости работы.
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,045
Записей в блоге: 1
19.05.2017, 13:44  [ТС]
Или даже так (вот теперь быдлокод ):
C#
1
2
3
4
5
6
7
8
9
10
public bool Метод сравнения(куча_исходных, куча_рабочих)
{
    If(Сравнить_количество_и_выдать_неравенство) return не_равны;
 
    var НайтиАйтем = куча_исходных.FirstOrDefault(сравнить_и_найти_по_уникальному);
 
    if(НайтиАйтем == null)  return не_равны;
 
//Дальше портяна из ифов
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
19.05.2017, 13:44
Помогаю со студенческими работами здесь

Сравнение коллекций и последующая модификация
Есть 2 коллекции ObservableCollection&lt;CollectionItem&gt; CollectionOne и ObservableCollection&lt;CollectionItem&gt; CollectionTwo содержащие по 5...

Быстрое сравнение файлов на сервере и у юзера
Добрый день! На текущий момент на сервере лежит xml с хешами файлов. Файл качается, берутся хеши файлов и сравниваются с хешами в xml....

Быстрое сравнение двух строк посимвольно
Задание: даны две строки, можно ли путем вычеркивания символов получить из строки2 строку1, длины строк от 1 до 106 Все работает, но...

Сравнение коллекций
Доброго времени суток) Есть код: package ru.myscanner.scannerth; import java.io.File; import java.util.ArrayList; import...

Сравнение коллекций во вложенных цикле
Существует следующая проблема. Есть коллекции, которые нужно сравнить с коллекцией word, и если слово совпадает, то его нужно удалить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru