СиППО (67-73) (Ответы на все вопросы)
Описание файла
Файл "СиППО (67-73)" внутри архива находится в папке "Ответы на все вопросы". Документ из архива "Ответы на все вопросы", который расположен в категории "". Всё это находится в предмете "системное и прикладное программное обеспечение (сппо)" из 6 семестр, которые можно найти в файловом архиве НИУ «МЭИ» . Не смотря на прямую связь этого архива с НИУ «МЭИ» , его также можно найти и в других разделах. Архив можно найти в разделе "к экзамену/зачёту", в предмете "системное и прикладное программное обеспечение (сппо)" в общих файлах.
Онлайн просмотр документа "СиППО (67-73)"
Текст из документа "СиППО (67-73)"
67.Ламбда-выражения и их использование на LINQ
68.Две разновидности синтаксиса на LINQ
69.Отложенное выполнение операторов на LINQ
70.Операторы Select, Where, Take, Skip, TakeWhile, SkipWhile
71.Агрегирующие функции на LINQ
72.Группировка данных на LINQ
73.Оператор соединения на LINQ
67.Ламбда-выражения и их использование на LINQ
Простейший запрос состоит из одной входной последовательности и одного оператора. Например, мы можем применить оператор where к строковому массиву и извлечь те его элементы, длина которых не меньше четырех символов. Поскольку стандартные операторы запроса реализованы в виде методов расширения, мы можем вызвать Where непосредственно ДЛЯ массива names так, словно это метод экземпляра:
IEnumerable<string> filteredNames = names."Where (n => n.Length >= 4);
Большинство операторов запроса принимает лямбда-выражение в качестве аргумента. Лямбда-выражение помогает направить и сформировать запрос. В нашем примере лямбда-выражение выглядит так:
n => п.Length >= 4
Входной аргумент соответствует входному элементу. В этом случае входной аргумент n представляет имя в массиве и имеет тип string. Оператор where требует, чтобы лямбда-выражение возвращало значение типа bool. Когда оно истинно, элемент должен быть включен в выходную последовательность.
Будем называть такие запросы лямбда-запросами
Чтобы строить более сложные запросы, вы добавляете новые операторы, образуя цепочку. Например, в следующем запросе из массива извлекаются все строки с буквой "а", после чего они сортируются по длине и переводятся в верхний регистр:
string[] names = {"Tom","Dick","Harry","Mary","Jay" }; IEnumerable<string> query = names.Where (n => n.Contains ("a")) .OrderBy (n => n.Length) .Select (n => n.ToUpper());
foreach (string name in query)
Console.Write (name + "|");
Результат: JAY|MARY|HARRY|
Примечание
Оператор запроса никогда не изменяет входную последовательность. Вместо нее он возвращает новую. Это соответствует парадигме функционального программирования, из которой исходит LINQ.
Когда операторы запроса выстраиваются в цепочку, как в нашем примере, выходная последовательность одного оператора становится входной для следующего.
В предыдущих примерах мы передавали оператору where такое лямбда-выражение:
n => n.Contains ("а") // На входе строка,
// на выходе булево выражение
Предназначение лямбда-выражения зависит от конкретного оператора запроса. С оператором where оно показывает, должен ли элемент попадать в выходную последовательность. У оператора OrderBy лямбда-выражение отображает каждый элемент входной последовательности на ключ сортировки, а у оператора select оно определяет, как должен быть преобразован элемент из входной последовательности перед подачей его в выходную.
Примечание
В операторе запроса лямбда-выражение всегда относится к отдельным элементам входной последовательности, а не к последовательности в целом.
Вы можете относиться к лямбда-выражению как к обратному вызову. Оператор запроса вычисляет значение лямбда-выражения "по требованию",— как правило, один раз для каждого элемента входной последовательности. Лямбда-выражения позволяют вам внести свою логику в операторы запроса. Это делает операторы запроса гибкими и в то же время простыми по внутреннему устройству. Приведем полную реализацию метода Enumerable.Where, опустив то, что касается обработки исключений:
public static IEnumerable<TSource> Where<TSource> (
this IEnumerable<TSource> source,
Func<TSource,bool> predicate)
{
foreach (TSource element in source)
if (predicate (element))
yield return element;
}
Лямбда-выражения и типы элементов
В стандартных операторах запроса используются следующие имена обобщенных типов.
Обозначение обобщенного типа | Смысл |
TSource | Тип элемента входной последовательности |
TResult | Тип элемента выходной последовательности — отличается от TSource |
TKey | Тип ключа, используемого при сортировке, группировании или объединении |
Тип TSource определяется входной последовательностью. Типы TResult и Tkey выводятся из вашего лямбда-выражения.
68.Две разновидности синтаксиса на LINQ
Простейший запрос состоит из одной входной последовательности и одного оператора. Например, мы можем применить оператор where к строковому массиву и извлечь те его элементы, длина которых не меньше четырех символов. Поскольку стандартные операторы запроса реализованы в виде методов расширения, мы можем вызвать Where непосредственно ДЛЯ массива names так, словно это метод экземпляра:
IEnumerable<string> filteredNames = names."Where (n => n.Length >= 4);
Большинство операторов запроса принимает лямбда-выражение в качестве аргумента. Лямбда-выражение помогает направить и сформировать запрос. В нашем примере лямбда-выражение выглядит так:
n => п.Length >= 4
Входной аргумент соответствует входному элементу. В этом случае входной аргумент n представляет имя в массиве и имеет тип string. Оператор where требует, чтобы лямбда-выражение возвращало значение типа bool. Когда оно истинно, элемент должен быть включен в выходную последовательность.
Будем называть такие запросы лямбда-запросами
Чтобы строить более сложные запросы, вы добавляете новые операторы, образуя цепочку. Например, в следующем запросе из массива извлекаются все строки с буквой "а", после чего они сортируются по длине и переводятся в верхний регистр:
string[] names = {"Tom","Dick","Harry","Mary","Jay" }; IEnumerable<string> query = names.Where (n => n.Contains ("a")) .OrderBy (n => n.Length) .Select (n => n.ToUpper());
foreach (string name in query)
Console.Write (name + "|");
//Результат: JAY|MARY|HARRY|
Вот как выглядит тот же запрос в соответствии с синтаксисом, облегчающим его восприятие:
string[] names = {
"Tom","Dick","Harry","Mary","Jay" };
IEnumerable<string> query =
from n in names
where n.Contains ("a") // Фильтровать элементы
orderby n.Length // Сортировать элементы
select n.ToUpper(); // Проецировать каждый элемент
foreach (string name in query)
Console.Write (name + "/");
// Результат: JAY/MARY/HARRY/
Запрос с синтаксисом, облегчающим восприятие, всегда начинается с конструкции from и заканчивается конструкцией либо select, либо group. Конструкция from объявляет переменную итерации (в данном случае n). Вы можете считать, что она используется для перебора элементов входной коллекции, аналогично оператору foreach.
Компилятор обрабатывает запросы с синтаксисом, облегчающим восприятие, переводя их в лямбда-синтаксис. Фактически это означает, что все, написанное вами в соответствии с синтаксисом, облегчающим восприятие, могло быть написано и с соблюдением лямбда-синтаксиса. Запрос из нашего примера транслируется в следующий код:
IEnumerable<string> query = names .Where (n => n.Contains ("a")).OrderBy (n => n.Length).Select (n => n.ToUpper());
Затем операторы Where, OrderBy и Select будут откомпилированы по тем же правилам, что и запросы, изначально написанные с соблюдением лямбда-синтаксиса.
Если оператор запроса не поддерживается синтаксисом, облегчающим восприятие, вы можете комбинировать этот синтаксис с лямбда-синтаксисом. Единственное требование, которое при этом выдвигается, — каждая составляющая "понятного" синтаксиса должна быть полной (то есть начинаться с конструкции from и заканчиваться конструкцией select ИЛИ group).
Например:
int count =
(
from name in names
where n.Contains ("a")
select name
).Count();
Бывают ситуации, в которых запросы со смешанным синтаксисом оказываются самыми эффективными в терминах функциональности и простоты. Избегайте оказывать предпочтение какому-то одному из двух вариантов синтаксиса. В противном случае вы не сможете уверенно и безошибочно писать запросы в смешанном синтаксисе!
69.Отложенное выполнение операторов на LINQ
Важной особенностью большинства операторов запроса является тот факт, что они выполняются не тогда, когда сконструированы, а при переборе элементов (то есть когда для соответствующего перечислителя вызывается метод MoveNext):
var numbers = new List<int>(); numbers.Add (1) ; // Построить запрос
IEnumerable<int> query = numbers.Select (n => n * 10);
numbers.Add (2); // "Незаметно" добавить еще один элемент
foreach (int n in query)
Console.Write (n + "|");
// 10|20|
Дополнительный элемент, который мы "тайком" добавили после конструирования запроса, попадает в результат, потому что ни фильтрация, ни сортировка не происходят, пока не начнет выполняться оператор foreach. Это называется отложенным или "ленивым" выполнением. Отложенное выполнение характерно для всех стандартных операторов запроса, кроме
· операторов, возвращающих один элемент или скалярное значение, таких как First или Count;
· операторов преобразования типа: ToArray, ToList, ToDictionary, ToLookup
Эти операторы приводят к немедленному выполнению запроса, потому что у возвращаемых ими результатов нет механизма, который обеспечивал бы отложенное выполнение. Например, метод Count возвращает целое число, которое затем никак не "перебирается". Следующий запрос выполняется немедленно:
int matches = numbers.Where (n => n < 2).Count(); // 1
Отложенное выполнение играет важную роль, потому что оно отделяет конструирование запроса от его выполнения. Это позволяет вам конструировать запрос за несколько шагов, а также делать LINQ-запросы к SQL.
70.Операторы Select, Where, Take, Skip, TakeWhile, SkipWhile
Проецирование
Оператор Select
Аргумент | Тип |
Исходная последовательность | IEnumerable<TSource> |
Селектор результата | TSource => TResult |
Синтаксис,облегчающий восприятие
select выражение_проецирования
Описание
От оператора select вы всегда получаете то количество элементов, которое было на входе. Однако каждый элемент может быть как угодно преобразован лямбда-функцией.
В следующем коде выбираются названия всех шрифтов, установленных на компьютере (из пространства имен System. Drawing):
IEnumerable<string> query =
from f in FontFamily.Families
select f.Name;
foreach (string name in query)
Console.WriteLine (name);
В этом примере предложение select преобразует объект FontFamily в его имя. Вот лямбда-эквивалент этого кода:
IEnumerable<string> query = FontFamily.Families.Select (f => f.Name);
Фильтрация
Метод | Описание |
Where | Возвращает подмножество элементов, удовлетворяющих данному условию |
Take | Возвращает первые count элементов и игнорирует остальные |
Skip | Игнорирует первые count элементов и возвращает остальные |
TakeWhile | Возвращает элементы из входной последовательности, пока предикат равен true. |
SkipWhile | Игнорирует элементы из входной последовательности, пока предикат равен true, а затем возвращает остальные |
Distinct | Возвращает коллекцию, из которой исключены повторяющиеся элементы |
Каким бы методом фильтрации вы ни пользовались, вы всегда получите либо то же самое, либо меньшее количество элементов по сравнению с оригинальной последовательностью. Вы никогда не получите больше! Кроме того, элементы на выходе идентичны оригинальным; они никак не преобразуются.
Оператор Where
Аргумент | Тип |
Исходная последовательность | IEnumerable<TSource> |
Предикат | TSource => bool |