Группировка элементов списка с помощью LINQ-запроса 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Группировка элементов списка с помощью LINQ-запроса



В данном примере используем стандартный шаблон LINQ-запроса для группи­ровки элементов списка. Программа формирует список продуктов питания. Следу­ет организовать такие LINQ-запросы, которые разделят искомый список на две группы по критерию цены (больше или меньше 90 руб. за единицу) и вычислят среднюю цену по каждой группе продуктов.

Для решения этой задачи запустим Visual Studio 2010 и выберем проект шабло­на Windows Forms Application, укажем имя Name — LinqЦеныНаПродукты. Да­лее, попав в конструктор формы, из панели элементов Toolbox (Панель элементов) перетащим тексто­вое поле TextBox для вывода в него групп списка. В свойствах текстового поля разрешим ввод множества строк, для этого свойство Multiline переведем в со­стояние true. Затем на вкладке программного кода введем текст, представленный в листинге 19.3.

Листинг 19.3. Группировка элементов списка с помощью LINQ-запросов

// Программа формирует список некоторых продуктов питания. Первый LINQ-запрос

// группирует элементы списка по критерию цены: в первом списке оказываются

// продукты, цена за единицу которых меньше или равна 90 руб., а во втором,

// соответственно, больше 90 руб. Второй LINQ-запрос вычисляет среднюю цену

// продукта по каждой группе. Результаты запросов выводятся в текстовое поле.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows.Forms;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace LinqЦеныНаПродукты

{

public partial class Form1: Form

{

public Form1()

{

InitializeComponent();

textBox1.Multiline = true;

base.Text = "Группировка элементов списка с помощью LINQ-запроса";

// Заполняем список продуктов:

List<Продукт> Продукты = new List<Продукт>{

new Продукт {Наименование="Творог", Цена=112.50F },

new Продукт {Наименование="Хлеб", Цена=18.75F },

new Продукт {Наименование="Печенье", Цена=93.75F },

new Продукт {Наименование="Чай", Цена=76.25F },

new Продукт {Наименование="Мясо", Цена=150.00F },

new Продукт {Наименование="Гречка", Цена=62.50F },

};

var Запрос1 =

from П in Продукты

group П by new

{

Критерий = П.Цена > 90,

}

into g

select g;

var Запрос2 =

from p in Продукты

group p by p.Цена > 90 into g

select new

{

g.Key,

СредЦенаПоГруппе = g.Average(p => p.Цена)

};

Single СредЦенаПоГруппе1 = Запрос2.ElementAt(0).СредЦенаПоГруппе;

Single СредЦенаПоГруппе2 = Запрос2.ElementAt(1).СредЦенаПоГруппе;

// Вывод результатов обоих запросов в текстовое поле:

foreach (var Группа in Запрос1)

{

if (Группа.Key.Критерий == false)

textBox1.Text += "\r\nЦены 90 руб или меньше:";

else

textBox1.Text += "\r\nЦены больше 90 руб:";

foreach (var Прод in Группа)

{

textBox1.Text += String.Format("\r\n{0} - {1}",

Прод.Наименование, Прод.Цена);

}

if (Группа.Key.Критерий == false)

textBox1.Text += String.Format(

"\r\nСредняя цена по данной группе = {0} руб.\r\n",

СредЦенаПоГруппе2);

else

textBox1.Text += String.Format(

"\r\nСредняя цена по данной группе = {0} руб.\r\n",

СредЦенаПоГруппе1);

}

}

}

public class Продукт

{

public String Наименование { get; set; }

public Single Цена { get; set; }

}

}

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

Фрагмент работы программы показан на рис. 19.3.

Рисунок 19.3 - Группировка списка с помощью LINQ-запросов

Убедиться в работоспособности программы можно, открыв решение LinqЦеныНаПродукты.sln папки LinqЦеныНаПродукты.

5.4 LINQ-запрос к словарю данных Dictionary

Замечательной структурой данных является словарь Dictionary. Он представ­ляет собой совокупность (коллекцию) ключей и значений. То есть каждый элемент (запись), добавляемый в словарь, состоит из значения Value и связанного с ним ключа Key. Извлечение значения по его ключу происходит очень быстро, посколь­ку класс Dictionary<Key,Value> реализован как хэш-таблица. Каждый ключ в словаре Dictionary<Key,Value> должен быть уникальным, т. е. единственным в своем роде, эксклюзивным. При добавлении в коллекцию Dictionary очередного элемента так называемый компаратор проверяет на равенство уникальность нового ключа. Ключ не может быть пустым (null), а значение может, если тип значения value является ссылочным типом. Возможно создание словаря, в котором не раз­личается регистр символов. Использование словаря Dictionary может существен­но повлиять на эффективность алгоритма, на простоту его понимания и легкость программной реализации.

Задача, решаемая в данном примере, состоит в том, чтобы продемонстрировать возможность выбора элементов из словаря данных Dictionary с помощью LINQ-запроса. В начале программы зададим массив сотрудников некого учреждения, а затем массив сотрудников преобразуем в словарь Dictionary. Причем в качестве ключа к каждому элементу словаря зададим имя сотрудника, которое является уни­кальным. По ключу можно получить все остальные сведения о сотруднике, запи­санные в словарь. Кроме того, с помощью LINQ-запроса к словарю можно полу­чать новую коллекцию сотрудников по какому-либо условию (предложение where). Здесь мы зададим выбор сотрудников, чей возраст превышает 33 года (возраст Ии­суса Христа). ’

Для решения этой задачи запустим Visual Studio 2010 и выберем проект шабло­на Console Application, укажем имя Name — LinqDictionary. Затем на вкладке про­граммного кода введем текст, представленный в листинге 19.4.

Листинг 19.4. Организация LINQ-запроса к словарю Dictionary

// Задаем массив сотрудников учреждения. Из этого массива создаем словарь

// сотрудников, а в качестве ключа к этому словарю выбираем имя сотрудника.

// С помощью LINQ-запроса из массива сотрудников выбираем тех, чей возраст

// превышает 35 лет. При выводе результата запроса на печать учитываем, что

// говоря про возраст, мы говорим "47 лет", но "34 года". То есть если из возраста

// вычесть число кратное 10, то при остатке меньше 5, говорят, например, "34 года",

// а при остатке больше или равно 5, говорят "47 лет".

using System;

using System.Linq;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace LinqDictionary

{

class Program

{

static void Main(string[] args)

{

Console.Title = "LINQ-запрос к словарю Dictionary";

// Создаем массив сотрудников учреждения:

var Сотрудники = new[] {

new {Имя = "Карапузова Ирина", Возраст = 27, КуритЛи = true },

new {Имя = "Зиборов Виктор", Возраст = 47, КуритЛи = false },

new {Имя = "Ломачинская Светлана", Возраст = 31, КуритЛи = false },

new {Имя = "Стороженко Светлана", Возраст = 34, КуритЛи = false },

new {Имя = "Еременко Татьяна", Возраст = 22, КуритЛи = true },

new {Имя = "Погребицкий Олег", Возраст = 42, КуритЛи = true }

};

// Доступ к элементу массива Сотрудники можем иметь через его индекс:

var t = Сотрудники[2];

// Строим LINQ-запрос к массиву сотрудников; выбираем тех, возраст

// которых больше 33 лет:

// var СписокВзрослыхСотрудников = from Сотрудник in Сотрудники

// where Сотрудник.Возраст >= 33

// orderby Сотрудник.Имя

// select Сотрудник;

// Из массива сотрудников создаем словарь сотрудников, в котором

// ключом является имя сотрудника:

var СловарьСотрудников = Сотрудники.ToDictionary(Ключ => Ключ.Имя);

// В этом случае очень удобным становится доступ к сведениям о

// сотруднике по его имени:

Boolean КуритЛиЗиборов = СловарьСотрудников["Зиборов Виктор"].КуритЛи;

int ВозрастЗиборова = СловарьСотрудников["Зиборов Виктор"].Возраст;

Console.WriteLine("Сотруднику Зиборову Виктору - {0} лет\n",

ВозрастЗиборова);

// Строим LINQ-запрос к словарю сотрудников; выбираем тех, возраст

// которых больше 33 лет:

var СписокВзрослыхСотрудников =

from Сотрудник in СловарьСотрудников

where Сотрудник.Value.Возраст >= 33

orderby Сотрудник.Value.Имя

select new

{

Сотрудник.Key,

Сотрудник.Value.Возраст,

ЛетИлиГода = Сотрудник.Value.Возраст - 10F *

Math.Truncate(Сотрудник.Value.Возраст / 10F) >= 5

};

 

// Вывод результата запроса на консоль:

Console.WriteLine("Список сотрудников, старше 33 лет:");

foreach (var x in СписокВзрослыхСотрудников)

Console.WriteLine("{0}, возраст - {1} {2} ", x.Key, x.Возраст,

x.ЛетИлиГода? "лет": "года");

Console.ReadKey();

}

}

}

Представленный текст программы очевиден. Вначале задаем массив сотрудни­ков учреждения, в этом массиве всего 6 элементов. В комментарии показано, как можно организовать LINQ-запрос к заданному массиву. Далее массив конвертиру­ем в словарь сотрудников, задавая в качестве ключа имя сотрудника. Затем органи­зуем LINQ-запрос к словарю Dictionary, выбираем в новую коллекцию (список) тех, чей возраст превышает 33 года. Учитываем, что при выводе на консоль списка выбранных сотрудников мы говорим "47 лет", но "34 года". То есть если из возрас­та вычесть число, кратное 10, то при остатке меньше 5 говорят, например, "34 го­да", а при остатке больше или равном 5 говорят "47 лет". Число, кратное 10, мы вычисляем, используя функцию Math.Truncate, которая возвращает целую часть числа, поданную на ее вход. В этом алгоритме мы использовали булеву перемен­ную ЛетИлиГода, которая определяет (по принципу "да" или "нет") следует писать "лет" или "года".

Результат работы программы показан на рис. 19.4

 

 

Рисунок 19.4 - Запрос к словарю данных на "взрослых" сотрудников

Убедиться в работоспособности программы можно, открыв решение LinqDic- tionary.sln папки LinqDictionary.



Поделиться:


Последнее изменение этой страницы: 2016-04-26; просмотров: 399; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.230.82 (0.05 с.)