Операции Distinct, Union, Except и Intersect

Операции множеств используются для выполнения математических операций с множествами на последовательностях.
Distinct
Операция Distinct удаляет дублированные элементы из входной последовательности. У операции Distinct есть один прототип, описанный ниже:
Эта операция возвращает объект, перечисляющий элементы входной последовательности source и выдающий последовательность, в которой каждый элемент не эквивалентен предыдущим выданным. Эквивалентность элементов определяется методами GetHashCode и Equals.
Давайте рассмотрим пример использования операции Distinct:

Union
Операция Union возвращает объединение множеств из двух исходных последовательностей. У этой операции имеется один прототип, описанный ниже:
Эта операция возвращает объект, который сначала перечисляет элементы последовательности по имени first, выдавая последовательность, в которой каждый элемент не эквивалентен предыдущим выданным, затем перечисляет вторую входную последовательность second, опять-таки, выдавая последовательность без повторений. Эквивалентность элементов определяется методами GetHashCode и Equals.
Чтобы продемонстрировать разницу между операцией Union и описанной ранее операцией Concat, в примере, представленном ниже, создаются последовательности first и second из массива cars, что приведет к дублированию пятого элемента в обеих последовательностях. Затем отображается количество элементов в массиве cars, а также в последовательностях first и second, наряду с количеством элементов в конкатенированной и объединенной последовательностях:
В конечном итоге последовательность concat должна иметь на один элемент больше, чем массив cars. Последовательность union должна содержать то же количество элементов, что и массив cars. Это доказывают результаты выполнения кода:

Intersect
Операция Intersect возвращает пересечение множеств из двух исходных последовательностей. Операция Intersect имеет один прототип, описанный ниже:
Эта операция возвращает объект, который сначала перечисляет элементы последовательности по имени first, выбирая оттуда каждый элемент, который не эквивалентен предыдущему выбранному элементу. Затем он перечисляет вторую входную последовательность, помечая любой элемент, имеющийся в обеих последовательностях, для включения в выходную последовательность. Затем осуществляется проход по помеченным элементам, с помещением их в выходную последовательность в том порядке, в котором они были собраны. Эквивалентность элементов определяется с помощью методов GetHashCode и Equals.
Чтобы продемонстрировать применение операции Intersect, ниже используются операции Take и Skip для генерации двух последовательностей и получения некоторого их перекрытия, как в примере с Union, где был намеренно дублирован пятый элемент. После вызова операции Intersect на этих двух сгенерированных последовательностях в возвращаемой последовательности intersect должен оказаться только дублированный пятый элемент:
В конечном итоге должна быть получена последовательность auto, которая состоит только из одного элемента, содержащего дублированный пятый элемент массива cars — Chevrolet:

Итак, LINQ работает! Насколько часто вам приходилось ранее выполнять операции над множествами элементов из двух коллекций? Было ли это трудно? Благодаря LINQ, все сложности в прошлом.
Except
Операция Except возвращает последовательность, содержащую все элементы первой последовательности, которых нет во второй последовательности. Эта операция имеет один прототип, описанный ниже:
Эта операция возвращает объект, который при перечислении перебирает элементы входной последовательности по имени second, собирая все элементы, которые не эквивалентны ранее собранным. Затем происходит перечисление входной последовательности first, с выдачей каждого ее элемента, которого нет в коллекции из второй последовательности. Эквивалентность одного элемента другому определяется с использованием их методов GetHashCode и Equals.
В следующем примере используются два массива arr1 и arr2. С помощью операции Except будут удалены взаимоисключающие элементы коллекций:
Как объединить две коллекции c
LINQ предоставляет несколько методов для работы с коллекциями как с множествами, а именно находить их разность, объединение и пересечение.
Разность последовательностей
С помощью метода Except() можно получить разность двух последовательностей:
В данном случае из массива soft убираются все элементы, которые есть в массиве hard . Результатом операции будут два элемента:
Пересечение последовательностей
Для получения пересечения последовательностей, то есть общих для обоих наборов элементов, применяется метод Intersect :
Так как оба набора имеют только один общий элемент, то соответственно только он и попадет в результирующую выборку:
Удаление дубликатов
Для удаления дублей в наборе используется метод Distinct :
Объединение последовательностей
Для объединения двух последовательностей используется метод Union . Его результатом является новый набор, в котором имеются элементы, как из первой, так и из второй последовательности. Повторяющиеся элементы добавляются в результат только один раз:
Результатом операции будет следующий набор:
Если же нам нужно простое объединение двух наборов, то мы можем использовать метод Concat :
В этом случае те элементы, которые встречаются в обоих наборах, дублируются в резутирующей последовательности.
Последовательное применение методов Concat и Distinct будет подобно действию метода Union.
Работа со сложными объектами
Для сравнения объектов в последовательностях применяются реализации методов GetHeshCode() и Equals(). Поэтому если мы хотим работать с последовательностями, которые содержат объекты своих классов и структур, то нам необходимо определить для них подобные методы:
Здесь объекты Person сравниваются исходя из значения их свойства Name — если имена равны, то и объекты Person равны. Консольный вывод:
Joining two lists together
If I have two lists of type string (or any other type), what is a quick way of joining the two lists?
The order should stay the same. Duplicates should be removed (though every item in both links are unique). I didn’t find much on this when googling and didn’t want to implement any .NET interfaces for speed of delivery.
![]()
![]()
15 Answers 15
This preserves the order of the lists, but it doesn’t remove any duplicates (which Union would do).
This does change list a . If you wanted to preserve the original lists then you should use Concat (as pointed out in the other answers):
This returns an IEnumerable as long as a is not null.
![]()
![]()
The way with the least space overhead is to use the Concat extension method.
It creates an instance of IEnumerable<T> which will enumerate the elements of list1 and list2 in that order.
The Union method might address your needs. You didn’t specify whether order or duplicates was important.
Take two IEnumerables and perform a union as seen here:
Something like this:
Or, you can use the ‘Union’ extension method that is defined in System.Linq. With ‘Union’, you can also specify a comparer, which can be used to specify whether an item should be unioned or not.
![]()
It’s working fine I think so. As previously said, Concat returns a new sequence and while converting the result to List, it does the job perfectly. Implicit conversions may fail sometimes when using the AddRange method.
![]()
If some item(s) exist in both lists you may use
![]()
As long as they are of the same type, it’s very simple with AddRange:
![]()
![]()
![]()
![]()
one way: List.AddRange() depending on the types?
![]()
One way, I haven’t seen mentioned that can be a bit more robust, particularly if you wanted to alter each element in some way (e.g. you wanted to .Trim() all of the elements.
//Get the products from the both arrays //excluding duplicates.
![]()
The two options I use are:
However I noticed as I used that when using the AddRange method with a recursive function, that calls itself very often I got an SystemOutOfMemoryException because the maximum number of dimensions was reached.
(Message Google Translated)
The array dimensions exceeded the supported range.
LINQ в C#: объединение коллекций
Кроме фильтрации, выбора и группировки последовательностей в LINQ C# также предусмотрен ряд методов, позволяющих объединять как однородные, так и разнородные (содержащие элементы различных типов данных) коллекции.
Метод Concat
Метод Concat объединяет две однородные коллекции. Например,
Метод Join
Позволяет объединить две разнородные коллекции по определенному признаку (ключу). Например, у нас уже есть класс, содержащий данные каких-то измерений:
Данные о том, кто именно проводил эти измерения содержатся в другом классе:
Коллекции будут выглядеть следующим образом:
Ключом, т.е. признаком по которому мы будем объединять две коллекции с помощью метода LINQ Join может выступать название измерения, то есть — это поле Name у класса DataObject и поле MeasurementName у класса Measurement . Объединим две коллекции следующим образом:
Метод Zip
Объединяет две коллекции последовательно в соответствии с их индексами, то есть первый элемент первой коллекции соединяется с первым элементов второй коллекции, второй элемент первой коллекции — со вторым элементов второй коллекции и так далее.
Метод Zip не проводит никаких проверок на равенство ключей, а просто «механически» соединяет две разнородные коллекции. Результат:
Итого
Сегодня мы рассмотрели три метода объединения коллекций в LINQ C#: Concat — объединяет две однородные коллекции, Zip — объединяет две разнородные коллекции, Join — объединяет две разнородные коллекции по ключу.