Содержание
Кроме фильтрации, выбора и группировки последовательностей в LINQ C# также предусмотрен ряд методов, позволяющих объединять как однородные, так и разнородные (содержащие элементы различных типов данных) коллекции.
Метод Concat
Метод Concat объединяет две однородные коллекции. Например,
int[] integers = { 1, 2, 3, 4 };
int[] integers2 = { 5, 6, 7, 8 };
var result = integers.Concat(integers2);
foreach (int i in result)
Console.Write($"{i} ");
Вывод консоли
Метод Join
Позволяет объединить две разнородные коллекции по определенному признаку (ключу). Например, у нас уже есть класс, содержащий данные каких-то измерений:
public class DataObject
{
public string Name { get; set; }
public double Value { get; set; }
public DateTime Date { get; set; }
public override string ToString()
{
return $"{Name} {Value} {Date}";
}
}
Данные о том, кто именно проводил эти измерения содержатся в другом классе:
class Measurement
{
public string MeasurementName { get; set; }
public string Person { get; set; }
}
Коллекции будут выглядеть следующим образом:
List<DataObject> objects = new List<DataObject>()
{
new DataObject {Name = "Измерение №1", Value = 12.5, Date = DateTime.Now },
new DataObject {Name = "Измерение №2", Value = 12.5, Date = DateTime.Now },
new DataObject {Name = "Измерение №3", Value = 80.5, Date = DateTime.Now.AddMonths(1) },
new DataObject {Name = "Измерение №4", Value = 11.3, Date = DateTime.Now.AddDays(7) },
new DataObject {Name = "Измерение №5", Value = 10.7, Date = DateTime.Now.AddHours(2.5) }
};
List<Measurement> measurements = new List<Measurement>()
{
new Measurement {MeasurementName = "Измерение №1", Person = "Иван Иванов" },
new Measurement {MeasurementName = "Измерение №2", Person = "Петр Петров" },
new Measurement {MeasurementName = "Измерение №3", Person = "Семен Слепаков" },
new Measurement {MeasurementName = "Измерение №4", Person = "Вася Пупкин" },
new Measurement {MeasurementName = "Измерение №5", Person = "Николай Николаев" }
};
Ключом, т.е. признаком по которому мы будем объединять две коллекции с помощью метода LINQ Join может выступать название измерения, то есть — это поле Name у класса DataObject и поле MeasurementName у класса Measurement. Объединим две коллекции следующим образом:
var result = measurements.Join(objects, // <-- вторая коллекция
p => p.MeasurementName, // свойство-ключ объекта из первой коллекции
t => t.Name, // свойство-ключ объекта из второй коллекции
(p, t) => new { Name = p.MeasurementName, Person = p.Person, Value = t.Value, Date = t.Date}); //что хотим видеть в результате
Результат:
Измерение №2 Петр Петров 12,5 06.11.2021 18:35:56
Измерение №3 Семен Слепаков 80,5 06.12.2021 18:35:56
Измерение №4 Вася Пупкин 11,3 13.11.2021 18:35:56
Измерение №5 Николай Николаев 10,7 06.11.2021 21:05:56
Метод Zip
Объединяет две коллекции последовательно в соответствии с их индексами, то есть первый элемент первой коллекции соединяется с первым элементов второй коллекции, второй элемент первой коллекции — со вторым элементов второй коллекции и так далее.
List<DataObject> objects = new List<DataObject>()
{
new DataObject {Name = "Измерение №1", Value = 12.5, Date = DateTime.Now },
new DataObject {Name = "Измерение №2", Value = 2.5, Date = DateTime.Now },
new DataObject {Name = "Измерение №3", Value = 12.5, Date = DateTime.Now },
new DataObject {Name = "Измерение №4", Value = 80.5, Date = DateTime.Now.AddMonths(1) },
new DataObject {Name = "Измерение №5", Value = 11.3, Date = DateTime.Now.AddDays(7) },
new DataObject {Name = "Измерение №6", Value = 10.7, Date = DateTime.Now.AddHours(2.5) },
new DataObject {Name = "Измерение №7", Value = 10.7, Date = DateTime.Now.AddHours(2.5) }
};
List<Measurement> measurements = new List<Measurement>()
{
new Measurement {MeasurementName = "Измерение №3", Person = "Иван Иванов" },
new Measurement {MeasurementName = "Измерение №5", Person = "Петр Петров" },
new Measurement {MeasurementName = "Измерение №6", Person = "Семен Слепаков" },
new Measurement {MeasurementName = "Измерение №7", Person = "Вася Пупкин" },
new Measurement {MeasurementName = "Измерение №8", Person = "Николай Гиколаев" }
};
var result = measurements.Zip(objects, // <-- вторая коллекция
(p, t) => new { Name = p.MeasurementName, ObjectName = t.Name, Person = p.Person, Value = t.Value, Date = t.Date}); //что хотим ыидеть в результате
foreach (var item in result)
{
Console.WriteLine($"{item.Name} - {item.ObjectName} {item.Person} {item.Value} {item.Date}");
}
Метод Zip не проводит никаких проверок на равенство ключей, а просто «механически» соединяет две разнородные коллекции. Результат:
Измерение №5 — Измерение №2 Петр Петров 2,5 06.11.2021 18:48:54
Измерение №6 — Измерение №3 Семен Слепаков 12,5 06.11.2021 18:48:54
Измерение №7 — Измерение №4 Вася Пупкин 80,5 06.12.2021 18:48:54
Измерение №8 — Измерение №5 Николай Николаев 11,3 13.11.2021 18:48:54
Итого
Сегодня мы рассмотрели три метода объединения коллекций в LINQ C#: Concat — объединяет две однородные коллекции, Zip — объединяет две разнородные коллекции, Join — объединяет две разнородные коллекции по ключу.