«Быстрое свидание» с LINQ

в 20:57, , рубрики: c#8, linq

Краткое описание основных методов LINQ простым языком, без терминов "проекция", "предикат", "делегат" и проч. От термина "лямбда-выражение" избавиться не удалось :)

Что такое LINQ

LINQ (Language Integrated Query) – это набор методов для работы с коллекциями.

Для простоты здесь будем называть коллекцией любой объект, который хранит несколько других объектов. Это может быть массив из чисел, или результат запроса к базе данных, или набор элементов, прочитанных из документа XML и т.д.

Методы LINQ вызываются в исходном коде, как и другие методы, пример на языке C#:

var result = nums.Select( n => n*2 );

Что такое лямбда-выражение

В предыдущем примере вызывается метод Select, за ним текст в скобках – это лямбда-выражение, краткая форма описания функции. Перед => указывается список входных параметров, в данном примере входной параметр один, он обозначается n. После => указывается программный код, который использует входные параметры и возвращает рассчитанное значение. В данном примере функция возвращает значение входного параметра, умноженное на 2.

«Быстрое свидание» с LINQ - 1

Цепочки вызовов методов LINQ

Для большинства методов LINQ результатом является тоже коллекция, к которой можно применить другой метод LINQ, например:

var result = nums.Select( n => n*2 ).Where( n => n > 4 ).OrderBy( n => n );

Так можно «цеплять» методы LINQ один за другим много раз.

Синтаксис метода и синтаксис запроса

В предыдущем примере методы LINQ вызываются, как любые другие методы в языке C#. Такой синтаксис называется синтаксис метода (Method Syntax).

Вызовы методов LINQ можно описать в более простом виде, используя синтаксис запроса (Query Syntax), например:

var result = from n in nums
                   where n*2 > 4
                   orderby n
                   select n*2;

Синтаксис запроса LINQ похож на SQL, но это не SQL, это другой синтаксис, и не надо искать соответствия.

Далее - краткое описание основных методов LINQ.

Select  - Цикл по коллекции

Описание коллекции для примера:

// создать коллекцию из 4-х чисел
int[] nums = { 1, 2, 3, 4 }; 

Синтаксис запроса (Query Syntax)

Пример в синтаксисе запроса:

var result1 = from n in nums select n+1;
«Быстрое свидание» с LINQ - 2

Разбор примера по частям:

from n in nums
соответствует
Для каждого элемента n в исходной коллекции nums

select n+1
соответствует
добавить в результирующую коллекцию значение, полученное из выражения n+1

Итоговый разбор примера:

var result1 = from n in nums select n+1

соответствует
Для каждого элемента n в исходной коллекции nums
добавить в результирующую коллекцию значение, полученное из выражения n+1.
Поместить результирующую коллекцию в переменную result1.

Синтаксис метода (Method Syntax)

Предыдущий пример в синтаксисе метода:

var result2 = nums.Select( n => n+1 );
«Быстрое свидание» с LINQ - 3

В методе Select в скобках описывается функция, которая возвращает элемент результирующей коллекции.

Входной параметр функции – после открывающей скобки и перед =>. В данном примере входной параметр функции - переменная n.

Во входном параметре функции передается элемент исходной коллекции.

Разбор примера по частям:

nums.Select
соответствует
Для каждого элемента в исходной коллекции nums

( n
соответствует
, используя переменную n для обозначения элемента коллекции nums,

=> n+1
соответствует
добавить в результирующую коллекцию значение, полученное из выражения n+1

Итоговый разбор примера:

var result2 = nums.Select( n => n+1 );

соответствует
Для каждого элемента в исходной коллекции nums
, используя переменную n для обозначения элемента коллекции nums,
добавить в результирующую коллекцию значение, полученное из выражения n+1.
Поместить результирующую коллекцию в переменную result2.

В обоих вариантах (синтаксис запроса и синтаксис метода) результирующая коллекция содержит числа: 2, 3, 4, 5

SelectMany  - Вложенный цикл (декартово произведение)

Описание коллекций для примера:

int[] nums = { 1, 2, 3, 4 }; // создать коллекцию из 4-х чисел
string[] chars = { "a", "b" }; // создать коллекцию из 2-х строк

Синтаксис запроса (Query Syntax)

Пример в синтаксисе запроса:

var result3 = from n in nums
              from c in chars
              select c + n.ToString();
«Быстрое свидание» с LINQ - 4

Разбор примера по частям:

from n in nums
from c in chars
соответствует
Для каждого элемента n в исходной коллекции nums
и для каждого элемента c в исходной коллекции chars

select c + n.ToString()
соответствует
добавить в результирующую коллекцию значение, полученное из выражения c + n.ToString()

Итоговый разбор примера:

var result3 = from n in nums
              from c in chars
              select c + n.ToString();

соответствует
Для каждого элемента n в исходной коллекции nums
и для каждого элемента c в исходной коллекции chars
добавить в результирующую коллекцию значение, полученное из выражения c + n.ToString().
Поместить результирующую коллекцию в переменную result3.

Синтаксис метода (Method Syntax)

Предыдущий пример в синтаксисе метода:

var result4 = nums.SelectMany( n => chars.Select( c => c + n.ToString() ));
«Быстрое свидание» с LINQ - 5

В методе SelectMany в параметре (т.е. в скобках) описывается функция, которая возвращает коллекцию.
Результирующая коллекция образуется путём объединения всех коллекций, полученных при вызове функции, описанной в скобках.
Входной параметр функции – после открывающей скобки и перед =>. В данном примере входной параметр функции - переменная n.
Во входном параметре функции передается элемент исходной коллекции. В данном примере исходная коллекция - nums, а в переменной n передаётся элемент коллекции nums.

Разбор примера по частям:

nums.SelectMany
соответствует
Для каждого элемента в исходной коллекции nums

( n
соответствует
, используя переменную n для обозначения элемента коллекции nums,

=>
соответствует
добавить в результирующую коллекцию объекты коллекции, полученной по следующему алгоритму:

chars.Select
соответствует
Для каждого элемента в исходной коллекции chars

( c
соответствует
, используя переменную c для обозначения элемента коллекции chars,

=> c + n.ToString()
соответствует
добавить в результирующую коллекцию значение, полученное из выражения c + n.ToString()

Итоговый разбор примера:

var result4 = nums.SelectMany( n => chars.Select( c => c + n.ToString() ));

соответствует
Для каждого элемента в исходной коллекции nums
, используя переменную n для обозначения элемента коллекции nums,
добавить в результирующую коллекцию объекты коллекции, полученной по следующему алгоритму:
Для каждого элемента в исходной коллекции chars
, используя переменную c для обозначения элемента коллекции chars,
добавить в результирующую коллекцию значение, полученное из выражения c + n.ToString().
Поместить результирующую коллекцию в переменную result4.

В обоих вариантах (синтаксис запроса и синтаксис метода) результирующая коллекция содержит строки: a1, b1, a2, b2, a3, b3, a4, b4

Еще один пример метода SelectMany

Описание коллекции для примера:

/* создать коллекцию из 2 объектов, 
   где каждый объект описывает категорию товаров 
   и содержит поля Name (название категории) и Goods (список названий товаров) */

var categories = new[] { new { Name = "Flowers", 
                               Goods = new string[] { "Rose", "Astra", "Tulip" } },
                         new { Name = "Candies", 
                               Goods = new string[] { "Bonbon", "Chocolate" } } };

Пример в синтаксисе запроса:

var goods1 = from c in categories
             from g in c.Goods
             select g;
«Быстрое свидание» с LINQ - 6

Предыдущий пример в синтаксисе метода:

var goods2 = categories.SelectMany(c => c.Goods );
«Быстрое свидание» с LINQ - 7

В обоих вариантах (синтаксис запроса и синтаксис метода) результирующая коллекция содержит общий список названий товаров: Rose, Astra, Tulip, Bonbon, Chocolate

Where  - Поиск элементов в коллекции по условиям поиска

Описание коллекции для примера:

// создать коллекцию из 3-х строк
string[] names = { "Tom", "Bob", "Nick" }; 

Синтаксис запроса (Query Syntax)

Пример в синтаксисе запроса:

var foundNames1 = from n in names
                 where n.Contains("o")
                 select n;
«Быстрое свидание» с LINQ - 8

Разбор примера по частям:

from n in names
соответствует
Для каждого элемента n в исходной коллекции names

where n.Contains("o")
соответствует
проверить условие n.Contains("o") (значение n содержит букву o).

select n;
соответствует
Если условие выполнилось, добавить в результирующую коллекцию значение n.

Итоговый разбор примера:

var foundNames1 = from n in names
                 where n.Contains("o")
                 select n;

соответствует
Для каждого элемента n в исходной коллекции names
проверить условие n.Contains("o") (значение n содержит букву o).
Если условие выполнилось, добавить в результирующую коллекцию значение n.
Поместить результирующую коллекцию в переменную foundNames1.

Синтаксис метода (Method Syntax)

Предыдущий пример в синтаксисе метода:

var foundNames2 = names.Where( n => n.Contains("o") );
«Быстрое свидание» с LINQ - 9

В методе Where в скобках описывается функция, которая возвращает true или false («Истина» или «Ложь»).
Входной параметр функции – после открывающей скобки и перед =>. В данном примере входной параметр функции - переменная n.
Во входном параметре функции передается элемент исходной коллекции.
Метод Where возвращает коллекцию элементов, для которых функция в скобках вернула true.

Разбор примера по частям:

names.Where
соответствует
Для каждого элемента в исходной коллекции names

( n
соответствует
, используя переменную n для обозначения элемента коллекции names,

=> n.Contains("o")
соответствует
проверить условие n.Contains("o") (значение n содержит букву o).
Если условие выполнилось, добавить в результирующую коллекцию значение n.

Итоговый разбор примера:

var foundNames2 = names.Where( n => n.Contains("o") );

соответствует
Для каждого элемента в исходной коллекции names
, используя переменную n для обозначения элемента коллекции names,
проверить условие n.Contains("o") (значение n содержит букву o).
Если условие выполнилось, добавить в результирующую коллекцию значение n.
Поместить результирующую коллекцию в переменную foundNames2.

В обоих вариантах (синтаксис запроса и синтаксис метода) результирующая коллекция содержит строки: Tom, Bob

Single  - Поиск одного элемента в коллекции

Описание коллекции для примера:

int[] nums = { 1, 2, 3, 4 }; // создать коллекцию из 4-х чисел

Синтаксис запроса (Query Syntax)

В синтаксисе запроса нет операторов по получению единственного элемента из коллекции.

Синтаксис метода (Method Syntax)

Пример в синтаксисе метода:

var result5 = nums.Single( n => n == 3 );
«Быстрое свидание» с LINQ - 10

В методе Single в скобках описывается функция, которая возвращает true или false («Истина» или «Ложь»).
Входной параметр функции – после открывающей скобки и перед =>. В данном примере входной параметр функции - переменная n.
Во входном параметре функции передается элемент исходной коллекции.
Метод Single возвращает элемент коллекции, для которого функция в скобках вернула true. Если таких элементов 0 или больше 1, возникнет исключение.

Если в методе Single пустые скобки, такой метод просто проверяет, что в коллекции один элемент, и возвращает его.

Разбор примера по частям:

nums.Single
соответствует
Для каждого элемента в исходной коллекции nums

( n
соответствует
, используя переменную n для обозначения элемента коллекции nums,

=> n == 3  
соответствует
проверить условие n == 3 (значение n равно 3)

Итоговый разбор примера:

var result5 = nums.Single( n => n == 3 );

соответствует
Для каждого элемента в исходной коллекции nums
, используя переменную n для обозначения элемента коллекции nums,
проверить условие n == 3 (значение n равно 3).
Если условие выполнилось для единственного элемента, поместить значение этого элемента в переменную result5.

В данном примере переменная result5 содержит число: 3

Join – Из двух исходных коллекций скомпоновать одну коллекцию, найдя соответствия между элементами исходных коллекций

Описание коллекций для примера:

/* создать коллекцию из 3-х объектов, 
   где каждый объект описывает студента 
   и содержит поля Name (имя студента) и FacultyId (код факультета) */

var students = new[] { new { Name = "Tom", FacultyId = 1 }, 
                     new { Name = "Bob", FacultyId = 2 }, 
                     new { Name = "John", FacultyId = 2 } };  

/* создать коллекцию из 2-х объектов, 
   где каждый объект описывает факультет 
   и содержит поля Name (название факультета) и Id (код факультета) */

var faculties = new[] { new { Name = "Faculty of Mathematics", Id = 1 }, 
                       new { Name = "Faculty of Physics",     Id = 2 } };  

Синтаксис запроса (Query Syntax)

Пример в синтаксисе запроса:

var result10 = from s in students
               join f in faculties
               on s.FacultyId equals f.Id
               select new { Name = s.Name, Faculty = f.Name };
«Быстрое свидание» с LINQ - 11

Разбор примера по частям:

from s in students
join f in faculties
соответствует
Для каждого объекта s в исходной коллекции students
и для каждого объекта f в исходной коллекции faculties

on s.FacultyId equals f.Id
соответствует
проверить условие - значение поля FacultyId (код факультета) в объекте коллекции students равно значению поля Id (код факультета) в объекте коллекции faculties.

select new { Name = s.Name, Faculty = f.Name };
соответствует
Если условие сравнения выполняется, добавить в результирующую коллекцию объект, где поле Name содержит имя студента из поля Name в объекте коллекции students, а поле Faculty содержит название факультета из поля Name в объекте коллекции faculties.

Итоговый разбор примера:

var result10 = from s in students
               join f in faculties
               on s.FacultyId equals f.Id
               select new { Name = s.Name, Faculty = f.Name };

соответствует
Для каждого объекта s в исходной коллекции students
и для каждого объекта f в исходной коллекции faculties
проверить условие - значение поля FacultyId (код факультета) в объекте коллекции students
равно значению поля Id (код факультета) в объекте коллекции faculties.
Если условие сравнения выполняется, добавить в результирующую коллекцию объект, где поле Name содержит имя студента из поля Name в объекте коллекции students, а поле Faculty содержит название факультета из поля Name в объекте коллекции faculties.
Поместить результирующую коллекцию в переменную result10.

Синтаксис метода (Method Syntax)

Предыдущий пример в синтаксисе метода:

var result11 = students.Join(faculties, 
                             s => s.FacultyId, 
                             f => f.Id, 
                             (s, f) => new 
                             { 
                               Name = s.Name, 
                               Faculty = f.Name 
                             });
«Быстрое свидание» с LINQ - 12

В методе Join в первый параметр передаётся коллекция, где будут искаться соответствующие элементы для каждого элемента исходной коллекции.
В данном примере в первый параметр передаётся коллекция faculties.
Т.о. для каждого объекта коллекции students будут искаться соответствующие объекты в коллекции faculties.

Второй параметр метода Join описывает функцию, которая возвращает значение, полученное из объекта первой коллекции, используемое для сравнения с объектом из второй коллекции.
В данном примере второй параметр метода Join описывает функцию:
s => s.FacultyId
Эта функция возвращает значение поля FacultyId (код факультета) из объекта коллекции students.

Третий параметр метода Join описывает функцию, которая возвращает значение, полученное из объекта второй коллекции, используемое для сравнения с объектом из первой коллекции.
В данном примере третий параметр метода Join описывает функцию:
f => f.Id
Эта функция возвращает значение поля Id (код факультета) из объекта коллекции faculties.
Т.о. при сравнении объекта студента и объекта факультета будет сравниваться код факультета.

Четвертый параметр метода Join описывает функцию, которая на вход получает объект первой коллекции и объект второй коллекции, для которых выполнилось условие сравнения.
Функция возвращает объект, который создаётся для данных двух объектов. Этот объект будет добавлен в результирующую коллекцию.
В данном примере четвертый параметр метода Join описывает функцию:
(s, f) => new { Name = s.Name, Faculty = f.Name }
Т.о. результирующая коллекция будет содержать объекты, в которых поле Name содержит имя студента, а поле Faculty содержит название факультета.

Разбор примера по частям:

students.Join(faculties
соответствует
Для каждого объекта в коллекции students
и для каждого объекта в коллекции faculties

s => s.FacultyId,
f => f.Id,
соответствует
сравнить значение поля FacultyId в объекте первой коллекции и значение поля Id в объекте второй коллекции.

(s, f) => new { Name = s.Name, Faculty = f.Name }
соответствует
Если условие сравнения выполняется, добавить в результирующую коллекцию объект, где поле Name содержит значение поля Name в объекте первой коллекции, а поле Faculty содержит значение поля Name в объекте второй коллекции.

Итоговый разбор примера:

var result11 = students.Join(faculties, 
                             s => s.FacultyId, 
                             f => f.Id, 
                             (s, f) => new { Name = s.Name, Faculty = f.Name });

соответствует
Для каждого объекта в коллекции students
и для каждого объекта в коллекции faculties
сравнить значение поля FacultyId в объекте первой коллекции и значение поля Id в объекте второй коллекции.
Если условие сравнения выполняется, добавить в результирующую коллекцию объект, где поле Name содержит значение поля Name в объекте первой коллекции, а поле Faculty содержит значение поля Name в объекте второй коллекции.
Поместить результирующую коллекцию в переменную result11.

В обоих вариантах (синтаксис запроса и синтаксис метода) результирующая коллекция содержит 3 объекта, где каждый объект описывает студента и содержит поля Name (имя студента) и Faculty (название факультета):

Name

Faculty

Tom

Faculty of Mathematics

Bob

Faculty of Physics

John

Faculty of Physics

GroupJoin – Из коллекции «мастер-таблица» и коллекции «дочерняя таблица» скомпоновать одну иерархическую коллекцию

Описание коллекций для примера:

/* создать коллекцию из 3-х объектов, 
   где каждый объект описывает отдел 
   и содержит поля Name (название отдела) и Id (код отдела) */

var departments = new[] { new { Name = "Purchasing Department", Id = 1 },
                     new { Name = "Sales Department", Id = 2 },
                     new { Name = "Analytics Department", Id = 3 } };

/* создать коллекцию из 4-х объектов, 
   где каждый объект описывает сотрудника 
   и содержит поля Name (имя сотрудника) и DepId (код отдела) */

var workers = new[] { new { Name = "Harry",     DepId = 1 },
                       new { Name = "George",   DepId = 1 },
                       new { Name = "Jessica",  DepId = 1 },
                       new { Name = "Emma",     DepId = 2 } };

Синтаксис запроса (Query Syntax)

Пример в синтаксисе запроса:

var result12 = from d in departments
               join w in workers
               on d.Id equals w.DepId
               into foundWorkers
               select new 
               { 
                   DepName    = d.Name, 
                   DepWorkers = foundWorkers 
               };
«Быстрое свидание» с LINQ - 13

Разбор примера по частям:

from d in departments
соответствует
Для каждого объекта d из коллекции departments

join w in workers
on d.Id equals w.DepId
соответствует
найти объекты в коллекции workers по условию:
значение поля Id (код отдела) в объекте из коллекции departments равно значению поля DepId (код отдела) в объекте из коллекции workers.

into foundWorkers
соответствует
Для каждого объекта из коллекции departments сохранить результаты поиска в переменной foundWorkers.

select new
{
  DepName    = d.Name,
  DepWorkers = foundWorkers
};
соответствует
Для каждого объекта из коллекции departments создать объект, в котором поле DepName содержит название отдела, а поле DepWorkers содержит коллекцию объектов из коллекции workers, найденных для данного отдела.

Итоговый разбор примера:

var result12 = from d in departments
               join w in workers
               on d.Id equals w.DepId
               into foundWorkers
               select new 
               { 
                   DepName    = d.Name, 
                   DepWorkers = foundWorkers 
               };

соответствует
Для каждого объекта d из коллекции departments
найти объекты в коллекции workers по условию:
значение поля Id (код отдела) в объекте из коллекции departments равно значению поля Id (код отдела) в объекте из коллекции workers.
Для каждого объекта из коллекции departments сохранить результаты поиска в переменной foundWorkers.
Для каждого объекта из коллекции departments создать объект, в котором поле DepName содержит название отдела, а поле DepWorkers содержит коллекцию объектов из коллекции workers, найденных для данного отдела.
Поместить результирующую коллекцию в переменную result12.

В результирующую коллекцию попадут и те объекты из коллекции departments, для которых не нашлись объекты из коллекции workers.

Синтаксис метода (Method Syntax)

Предыдущий пример в синтаксисе метода:

var result13 = departments.GroupJoin(workers,
                                      d => d.Id,
                                      w => w.DepId,
                                      (d, foundWorkers) => new 
                                      { 
                                          DepName    = d.Name, 
                                          DepWorkers = foundWorkers 
                                      });
«Быстрое свидание» с LINQ - 14

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

Второй параметр метода GroupJoin описывает функцию, которая возвращает значение, полученное из объекта первой коллекции, используемое для сравнения с объектом из второй коллекции.
В данном примере второй параметр метода GroupJoin описывает функцию:
d => d.Id
Эта функция возвращает значение поля Id (код отдела) из объекта коллекции departments.

Третий параметр метода GroupJoin описывает функцию, которая возвращает значение, полученное из объекта второй коллекции, используемое для сравнения с объектом из первой коллекции.
В данном примере третий параметр метода GroupJoin описывает функцию:
w => w.DepId
Эта функция возвращает значение поля DepId (код отдела) из объекта второй коллекции workers.
Т.о. при сравнении объекта отдела и объекта работника будет сравниваться код отдела.

Четвертый параметр метода GroupJoin описывает функцию, которая на вход получает объект первой коллекции и коллекцию объектов второй коллекции, найденных для данного объекта первой коллекции.
Функция возвращает объект, который будет добавлен в результирующую коллекцию.

В данном примере четвертый параметр метода GroupJoin описывает функцию:
(d, foundWorkers) => new
{
    DepName    = d.Name,
    DepWorkers = foundWorkers
});

Т.о. результирующая коллекция будет содержать объекты, в которых поле DepName содержит название отдела, а поле DepWorkers содержит коллекцию объектов из коллекции workers, найденных для данного отдела.

Разбор примера по частям:

departments.GroupJoin(workers
соответствует
Для каждого объекта в исходной коллекции departments
найти объекты в коллекции workers

d => d.Id,
w => w.DepId,
соответствует
по условию:
значение поля Id (код отдела) в объекте из исходной коллекции departments равно значению поля DepId (код отдела) в объекте из коллекции workers.

(d, foundWorkers) => new
{
    DepName    = d.Name,
    DepWorkers = foundWorkers
});
соответствует
Для каждого объекта из исходной коллекции departments создать объект, в котором поле DepName содержит название отдела, а поле DepWorkers содержит коллекцию объектов из коллекции workers, найденных для данного отдела.

Итоговый разбор примера:

var result13 = departments.GroupJoin(workers,
                                      d => d.Id,
                                      w => w.DepId,
                                      (d, foundWorkers) => new 
                                      { 
                                          DepName    = d.Name, 
                                          DepWorkers = foundWorkers 
                                      });

соответствует
Для каждого объекта в исходной коллекции departments
найти объекты в коллекции workers
по условию:
значение поля Id (код отдела) в объекте из исходной коллекции departments равно значению поля DepId (код отдела) в объекте из коллекции workers.
Для каждого объекта из исходной коллекции departments создать объект, в котором поле DepName содержит название отдела, а поле DepWorkers содержит коллекцию объектов из коллекции workers, найденных для данного отдела.
Поместить результирующую коллекцию в переменную result13.

В обоих вариантах (синтаксис запроса и синтаксис метода) результирующая коллекция содержит 3 объекта (соответствующих 3 объектам исходной коллекции departments), где каждый объект описывает отдел и содержит поле DepName (название отдела) и поле DepWorkers (коллекция объектов сотрудников отдела):

DepName

DepWorkers

Name

DepId

Purchasing Department

Harry

1

George

1

Jessica

1

Sales Department

Emma

2

Analytics Department

 

 

GroupBy - Разбить коллекцию на несколько коллекций, каждая из которых содержит элементы с одинаковыми значениями ключевых полей

Описание коллекции для примера:

/* создать коллекцию из 3-х объектов, 
   где каждый объект описывает студента и содержит поля Name и Age */
var people = new[] { new { Name = "Tom", Age = 24 }, 
                     new { Name = "Bob", Age = 25 }, 
                     new { Name = "John", Age = 25 } };  

Синтаксис запроса (Query Syntax)

Пример в синтаксисе запроса:

var ageGroups1 = from p in people
                 group p.Name by p.Age;
«Быстрое свидание» с LINQ - 15

Разбор примера по частям:

from p in people
соответствует
Из исходной коллекции people
, используя переменную p для обозначения объекта коллекции people,

group p.Name
соответствует
отобрать группы объектов, где каждый объект является значением p.Name

by p.Age
соответствует
, при этом в одну группу объектов попадают значения, полученные из объектов исходной коллекции с одинаковым значением поля Age

Итоговый разбор примера:

var ageGroups1 = from p in people
                 group p.Name by p.Age;

соответствует
Из исходной коллекции people,
, используя переменную p для обозначения объекта коллекции people,
отобрать группы объектов, где каждый объект является значением p.Name
, при этом в одну группу объектов попадают значения, полученные из объектов исходной коллекции с одинаковым значением поля Age.
Поместить результирующую коллекцию групп объектов в переменную ageGroups1.

Синтаксис метода (Method Syntax)

Предыдущий пример в синтаксисе метода:

var ageGroups2 = people.GroupBy( p => p.Age, p => p.Name );
«Быстрое свидание» с LINQ - 16

В методе GroupBy может быть от одного до трёх параметров

Первый параметр метода GroupBy описывает функцию, которая определяет ключ для группировки.
В данном примере первый параметр метода GroupBy описывает функцию:
p => p.Age
Эта функция возвращает значение поля Age из объекта коллекции people.
Т.о. в данном примере будут созданы группы объектов, соответствующих объектам коллекции people с одинаковыми значениями поля Age.

Второй параметр метода GroupBy описывает функцию, которая возвращает объект, который будет добавлен в результирующую группу элементов.
Этот параметр необязательный.
В данном примере второй параметр метода GroupBy описывает функцию:
p => p.Name
Т.о. в данном примере будут созданы группы объектов, где каждый объект содержит значение поля Name из объекта коллекции people.

Если в методе GroupBy указан только первый параметр (т.е. отсутствует второй параметр метода), тогда результирующие группы объектов будут созданы из объектов исходной коллекции.

Третий параметр метода GroupBy описывает функцию, которая сравнивает ключевые значения, полученные из функции, описанной в первом параметре метода GroupBy. Этот параметр необязательный.
Если в методе GroupBy отсутствует третий параметр, тогда ключевые значения сравниваются встроенным механизмом.

Разбор примера по частям:

people.GroupBy
соответствует
Из исходной коллекции people отобрать группы объектов

( p => p.Age
соответствует
, соответствующих объектам коллекции people с одинаковым значением поля Age.

, p => p.Name
соответствует
В результирующих группах объектов каждый объект содержит значение поля Name из объекта коллекции people.

Итоговый разбор примера:

var ageGroups2 = people.GroupBy( p => p.Age, p => p.Name );
соответствует
Из исходной коллекции people отобрать группы объектов
, соответствующих объектам коллекции people с одинаковым значением поля Age.
В результирующих группах объектов каждый объект содержит значение поля Name из объекта коллекции people.
Поместить результирующую коллекцию групп объектов в переменную ageGroups2.

В обоих вариантах (синтаксис запроса и синтаксис метода) результирующая коллекция групп объектов содержит 2 группы объектов:
Ключевое поле: 24, объекты в группе: Tom
Ключевое поле: 25, объекты в группе: Bob, John

Краткое описание других методов LINQ

Методы сортировки

OrderBy – сортировка по возрастанию
OrderByDescending - сортировка по убыванию
ThenBy - сортировка по возрастанию, с учетом предыдущей сортировки
ThenByDescending - сортировка по убыванию, с учетом предыдущей сортировки

Методы расчета агрегата (например, суммы значений всех элементов коллекции).

Sum - сумма значений всех элементов коллекции
Average - среднее значение всех элементов коллекции
Min – минимальное значение элемента коллекции
Max - максимальное значение элемента коллекции
Count – количество элементов в коллекции
Aggregate – результат операции, выполненной последовательно над всеми элементами коллекции (например, умножить все элементы друг на друга)

Методы проверки условий на элементах коллекции

 All – вернуть true, если условие выполняется для всех элементов коллекции
Any - вернуть true, если условие выполняется хотя бы для одного элемента коллекции
Contains - вернуть true, если коллекция содержит указанный элемент

Методы объединения и пересечения коллекций

Concat – объединить две коллекции, все элементы двух коллекций попадут в результирующую коллекцию
Except – вернуть коллекцию, содержащие элементы, которые присутствуют в первой коллекции и отсутствуют во второй коллекции
Intersect - вернуть коллекцию, содержащие элементы, которые одновременно присутствуют и в первой, и во второй коллекции
Union - объединить две коллекции, исключая дублирование

Методы пропуска элементов (аналоги пагинации)

Skip – вернуть коллекцию, где отсутствует заданное количество первых элементов
SkipLast - вернуть коллекцию, где отсутствует заданное количество последних элементы
SkipWhile – исключать из исходной коллекции элементы, начиная с первого, до тех пор, пока выполняется заданное условие. Вернуть коллекцию, содержащую все остальные элементы, начиная с первого, для которого не выполнилось условие.
Take - вернуть коллекцию, содержащую заданное количество первых элементов
TakeLast - вернуть коллекцию, содержащую заданное количество последних элементов
TakeWhile – вернуть коллекцию, включающую элементы из исходной коллекции, начиная с первого, до тех пор, пока выполняется заданное условие

Прочие методы

Cast – привести все элементы коллекции к указанному типу
Distinct - удалить повторяющиеся значения из коллекции
ToArray, ToDictionary, ToList – преобразовать коллекцию в коллекцию другого типа
ToLookup – вернуть коллекцию, содержащую пары «ключ-значение», представляющую собой словарь «один ко многим», аналог индекса в базе данных

Автор: alex1303

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js