Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.docx
Скачиваний:
13
Добавлен:
03.11.2018
Размер:
614.46 Кб
Скачать

5. Операторы соединения.

Операторы соединения применяются, когда требуется соединить две коллекции, элементы которых имеют общие атрибуты. Основным оператором соединения является оператор Join().

IEnumerable<V> Join<T, U, K, V>(this IEnumerable<T> outer,

IEnumerable<U> inner,

Func<T, K> outerKeySelector,

Func<U, K> innerKeySelector,

Func<T, U, V> resultSelector);

Как видим, оператор Join() требует задания двух коллекций (внешней и внутренней) и трёх функций. Первая функция порождает ключ из элемента внешней коллекции, вторая – из элемента внутренней коллекции, а третья функция продуцирует объект коллекции-результата. При выполнении соединения Join() итерируется по внешней коллекции и ищет соответствия с элементами внутренней коллекции. При этом возможны следующие ситуации:

  • Найдено одно соответствие – в результат включается один элемент.

  • Найдено множественное соответствие – результат содержит по элементу для каждого соответствия.

  • Соответствий не найдено – элемент не входит в результат.

Рассмотрим примеры использования оператора Join(). Для этого опишем коллекцию cit объектов класса Citizen.

public class Citizen

{

public int BirthYear { get; set; }

public string IDNumber { get; set; }

}

int year = DateTime.Now.Year;

var cit = new List<Citizen> {

new Citizen {BirthYear = year - 17, IDNumber = "KLM897"},

new Citizen {BirthYear = year - 18, IDNumber = "WEF442"},

new Citizen {BirthYear = year - 18, IDNumber = "HHH888"},

new Citizen {BirthYear = year - 25, IDNumber = "XYZ012"}};

Выполним оператор Join():

var r1 = gr.Join(cit, s => year - s.Age, c => c.BirthYear,

(s, c) => new {s.Name, c.IDNumber});

// r1 содержит следующие объекты:

// {Name = "Smirnov", IDNumber = "WEF442"}

// {Name = "Smirnov", IDNumber = "HHH888"}

// {Name = "Kuznetsov", IDNumber = "WEF442"}

// {Name = "Kuznetsov", IDNumber = "HHH888"}

Оператор GroupJoin() порождает набор, группируя элементы внутренней коллекции при нахождении соответствия с элементом внешней коллекции: Если же соответствие не найдено, в результат включается пустая группа.

IEnumerable<V> GroupJoin()<T, U, K, V>(this IEnumerable<T> outer,

IEnumerable<U> inner,

Func<T, K> outerKeySelector,

Func<U, K> innerKeySelector,

Func<T, IEnumerable<U>, V> resultSelector);

Ниже приведён пример использования GroupJoin().

var r3 = cit.GroupJoin(gr, c => c.BirthYear, s => year - s.Age,

(c, group) => new { c.IDNumber,

Names = group.Select(s => s.Name) });

foreach (var data in r3)

{

Console.WriteLine(data.IDNumber);

foreach (string s in data.Names)

{ // 1-я и 4-я группы пусты,

Console.WriteLine(s); // 2-я и 3-я содержат два элемента

}

}

Оператор Zip() порождает набор на основе двух исходных коллекций, выполняя заданное генерирование элементов. Длина результирующей коллекции равна длине меньшей из двух исходных коллекций.

IEnumerable<V> Zip<T, U, V>(this IEnumerable<T> first,

IEnumerable<U> second,

Func<T, U, V> resultSelector);

Дадим простейший пример использования Zip():

int[] numbers = { 1, 2, 3, 4 };

string[] words = { "one", "two", "three" };

var res = numbers.Zip(words, (f, s) => f + " " + s); // 3 элемента