Создание группового объединения

Как пояснялось ранее, оператор into можно использовать вместе с оператором join для создания группового объединения, образующего последовательность, в которой каждый результат состоит из элементов данных из первой последовательности и группы всех совпадающих элементов из второй последовательности. Примеры группового объединения не приводились выше потому, что в этом объединении нередко применяется анонимный тип. Но теперь, когда представлены анонимные типы, можно обратиться к простому примеру группового объединения.

В приведенном ниже примере программы групповое объединение используется для составления списка, в котором различные транспортные средства (автомашины, суда и самолеты) организованы по общим для них категориям транспорта: наземного, морского, воздушного и речного. В этой программе сначала создается класс Transport, связывающий вид транспорта с его классификацией. Затем в методе Main() формируются две входные последовательности. Первая из них представляет собой массив символьных строк, содержащих названия общих категорий транспорта: наземного, морского, воздушного и речного, а вторая — массив объектов типа Transport, инкапсулирующих различные транспортные средства. Полученное в итоге групповое объединение используется для составления списка транспортных средств, организованных по соответствующим категориям.

// Продемонстрировать применение простого группового объединения.

using System;

using System.Linq;

// Этот класс связывает наименование вида транспорта,

// например поезда, с общей классификацией транспорта:

// наземного, морского, воздушного или речного,

class Transport {

  public string Name { get; set; }

  public string How { get; set; }

  public Transport(string n, string h) {

    Name = n;

    How = h;

  }

}

class GroupJoinDemo {

  static void Main() {

    // Массив классификации видов транспорта,

    string[] travelTypes = {

      "Воздушный",

      "Морской",

      "Наземный",

      "Речной",

    };

    // Массив видов транспорта.

    Transport[] transports = {

      new Transport("велосипед", "Наземный"),

      new Transport ("аэростат", "Воздушный"),

      new Transport("лодка", "Речной"),

      new Transport("самолет", "Воздушный"),

      new Transport("каноэ", "Речной"),

      new Transport("биплан", "Воздушный"),

      new Transport("автомашина", "Наземный"),

      new Transport("судно", "Морской"),

      new Transport("поезд", "Наземный")

    };

    // Сформировать запрос, в котором групповое

    // объединение используется для составления списка

    // видов транспорта по соответствующим категориям,

    var byHow = from how in travelTypes

             join trans in transports

               on how equals trans.How

             into lst

             select new { How = how, Tlist = lst };

    // Выполнить запрос и вывести его результаты,

    foreach(var t in byHow) {

      Console.WriteLine("К категории <{0} транспорт> относится:", t.How);

      foreach(var m in t.Tlist)

        Console.WriteLine(" " + m.Name);

      Console.WriteLine();

    }

  }

}

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

К категории <Воздушный транспорт> относится:

 аэростат

 самолет

 биплан

К категории <Морской транспорт> относится:

 судно

К категории <Наземный транспорт> относится:

 велосипед

 автомашина

 поезд

К категории <Речной транспорт> относится:

 лодка

 каноэ

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

var byHow = from how in travelTypes

     join trans in transports

       on how equals trans.How

     into 1st

     select new { How = how, Tlist = 1st };

Этот запрос формируется следующим образом. В операторе from используется переменная диапазона how для охвата всего массива travelTypes. Напомним, что массив travelTypes содержит названия общих категорий транспорта: воздушного, наземного, морского и речного. Каждый вид транспорта объединяется в операторе join со своей категорией. Например, велосипед, автомашина и поезд объединяются с наземным транспортом. Но благодаря оператору into для каждой категории транспорта в операторе join составляется список видов транспорта, относящихся к данной категории. Этот список сохраняется в переменной lst. И наконец, оператор select возвращает объект анонимного типа, инкапсулирующий каждое значение переменной how (категории транспорта) вместе со списком видов транспорта. Именно поэтому для вывода результатов запроса требуются два цикла foreach.

foreach(var t in byHow) {

  Console.WriteLine("К категории <{0} транспорт> относится:", t.How);

  foreach(var m in t.Tlist)

    Console.WriteLine(" " + m.Name);

  Console.WriteLine();

}

Во внешнем цикле получается объект, содержащий наименование общей категории транспорта, и список видов транспорта, относящихся к этой категории. А во внутреннем цикле выводятся отдельные виды транспорта.

Более 800 000 книг и аудиокниг! 📚

Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением

ПОЛУЧИТЬ ПОДАРОК