C# linq union вопрос

Может ли кто-нибудь объяснить, как работает Union в LINQ?

Говорят, что он объединяет две последовательности и удаляет дубликаты.

Но могу ли я как-то настроить поведение удаления дубликатов - скажем, если я хочу использовать элемент из the second sequence в случае дублирования или из the first sequence.

Или даже если я хочу как-то объединить эти значения в результирующую последовательность?

Как это реализовать?


Обновлять

Наверно я неправильно описал проблему, допустим у нас есть какое-то значение:

class Value {
   String name
   Int whatever;
}

и используемый компаратор выполняет x.name == y.name проверку.

И допустим, что иногда я знаю, что должен взять элемент из второй последовательности, потому что его поле whatever новее/лучше, чем поле whatever первой последовательности.

В любом случае, я бы использовал вариант sequence1.Union(sequence2) или sequence2.Union(sequence1) методов.

Спасибо


person Yippie-Ki-Yay    schedule 11.12.2010    source источник


Ответы (3)


Вы можете использовать second.Union(first) вместо first.Union(second). Таким образом, он сохранит элементы из second, а не элементы из first.

person Thomas Levesque    schedule 11.12.2010

Когда объект, возвращаемый этим методом, перечисляется, Union перечисляет первый и второй в указанном порядке и возвращает каждый элемент, который еще не был возвращен.
http://msdn.microsoft.com/en-us/library/bb341731.aspx

Таким образом, элементы из любой последовательности, которую вы используете в качестве левого параметра, имеют приоритет над элементами из правого параметра.

Важно то, что это четко определенное и задокументированное поведение, а не просто детали реализации, которые могут измениться в следующей версии .net.

В качестве примечания, когда вы реализуете IEqualityComparer<T>, важно использовать согласованные Equals и GetHashCode. И в этом случае я предпочитаю явно предоставлять компаратор равенства методу объединения вместо того, чтобы Equals самого объекта возвращало true для объектов, которые не идентичны для всех целей.

person CodesInChaos    schedule 11.12.2010
comment
Спасибо, это необходимая информация: в частности, уверенность в том, что то, что могло быть загадочным поведением черного ящика, на самом деле задокументировано и не изменится без фанфар — предположительно, не изменится вообще. - person Marc L.; 21.03.2019

Если элементы являются дубликатами, то не имеет значения, из какого списка они взяты, если, конечно, ваш компаратор равенства не учитывает все свойства элемента.

Если они на самом деле не являются дубликатами, то они оба появятся в результирующем объединении.

ОБНОВЛЕНИЕ

Как минимум из вашей новой информации вы должны написать новый оператор равенства, который учитывает whatever. Вы не можете просто использовать sequence1.Union(sequence2) или sequence2.Union(sequence1), если только все элементы не хотят брать из той или иной последовательности.

В крайнем случае вам придется написать свой собственный метод расширения Union, который сделает это за вас.

person ChrisF    schedule 11.12.2010
comment
Это зависит от того, как вы определяете равенство... Если тип реализует IEquatable<T> (или OP явно указывает компаратор равенства), возможно, что сравнение не учитывает все члены. - person Thomas Levesque; 12.12.2010
comment
@ Томас - это подразумевалось в моем ответе. Возможно, я должен сделать это явным. - person ChrisF; 12.12.2010
comment
@Thomas - мое редактирование было вызвано вашим комментарием, но в течение 5 минут;) - person ChrisF; 12.12.2010