LINQ в C#: объединение коллекций

Кроме фильтрации, выбора и группировки последовательностей в 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} ");

Вывод консоли

1 2 3 4 5 6 7 8

Метод 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}); //что хотим видеть в результате

Результат:

Измерение №1 Иван Иванов 12,5 06.11.2021 18:35:56
Измерение №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 не проводит никаких проверок на равенство ключей, а просто «механически» соединяет две разнородные коллекции. Результат:

Измерение №3 — Измерение №1 Иван Иванов 12,5 06.11.2021 18:48:54
Измерение №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 — объединяет две разнородные коллекции по ключу.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии