Академический Документы
Профессиональный Документы
Культура Документы
1.2.
1. Подсчитать количество строк, содержащих заданную подстроку
2. Найти строки, начинающиеся с заданного символа
3. Найти в каждой строке число запятых
4.Найти строки, являющиеся изображениями чисел
5. Подсчитать сумму чисел, содержащихся в каждой строке
1.3.
1. лекарства (название, фирма-производитель, цена за упаковку,
количество упаковок).
2. издания (индекс, название, месячная стоимость, количество
месяцев подписки).
3. детали (название, фирма-изготовитель, количество модификаций),
4. студенты (шифр группы, ФИО, номер зачетки, зарплата отца,
зарплата матери, и количество членов семьи).
5. детали (название, материал, название операции, время
выполнения).
1.4.
1. Студенты (ФИО, номер зачетной книжки) и предметы (название,
ФИО преподавателя, название кафедры).
2. сотрудники предприятия (табельный номер, ФИО, паспортные
данные, адрес, дата рождения, пол, должность и количество детей),
и отделы (наименование, количество закрепленных помещений).
1
3. товары (наименование, цена единицы) и склады (номер, ФИО
кладовщика).
4.изделия (наименование, фирма-изготовитель) детали
(наименование, фирма-изготовитель, (наименование материала, цена
за грамм).
5. книги (регистрационный номер, количество страниц, год издания,
раздел - учебник, художественная общественно-политическая и т.д. )
и читатели (ФИО, домашний адрес, паспортные данные).
9
Рис. 42.
Список методов объекта names
10
В конструкции where (или вызове метода Where ()), LINQ позволяет
сортировать результирующие данные. Для этого существует ключевое слово
orderby:
var gueryResults2=from n in names where n.Equals(aName) orderby n select n;
Это сортировка по возрастанию. Для сортировки по убыванию
добавляется слово descending:
where n.Equals(aName) orderby n descending
Для отбора данных, удовлетворяюших учловию, можно применять
операции сравнения. Например:
int[] numbers = generateLotsOfNumbers(12345678);
var queryResults = from n in numbers where n < 1000 select n ;
foreach (int item in queryResults)
{ ListBox1.Items.Add(item.ConvertTo.String
Console.WriteLine(item); }
generateLotsOfNumbers - метод для генерации списка случайных чисел:
private static int[] generateLotsOfNumbers(int count)
{ Random generator = new Random();
int[] result = new int[count];
for (int i = 0; i < count; i++)
{ result[i] = generator.Next (); }
return result; }
LINQ предоставляет набор агрегатных операций, позволяющих
анализировать результаты запроса, не выполняя цикл по всем результатам.
Перечисленные ниже агрегатные операции чаще всего используются для
набора числовых результатов, таких как результаты предыдущего запроса.
Count () Подсчитывает количество результатов
Min () Минимальное значение результатов
Mах () Максимальное значение результатов
Average () Среднее значение числовых результатов
Sum () Сумма всех числовых результатов
Приведенный ниже код выводит в список различные числовые
характеристики подмножества запроса:
int[] numbers = generateLotsOfNumbers(2345678);
listBox1.Items.Add("Числовые агрегаты");
var queryResults = from n in numbers where n > 1000 select n;
listBox1.Items.Add("Количество чисел > 1000");
listBox1.Items.Add(Convert.ToString(queryResults.Count()));
listBox1.Items.Add("Максимальное из чисел > 1000");
listBox1.Items.Add(Convert.ToString(queryResults.Max()));
listBox1.Items.Add("Минимальное из чисел > 1000");
listBox1.Items.Add(Convert.ToString(queryResults.Min()));
listBox1.Items.Add("Среднее из чисел > 1000");
listBox1.Items.Add(Convert.ToString(queryResults.Average()));
listBox1.Items.Add("Сумма чисел > 1000");
11
listBox1.Items.Add(Convert.ToString(queryResults.Sum(n => (long)n)));
// 2. Query creation.
// numQuery is an IEnumerable<int>
var numQuery =
from num in numbers
where (num % 2) == 0
select num;
// 3. Query execution.
foreach (int num in numQuery)
{
Console.Write("{0,1} ", num);
}
}
}
12
Запрос указывает, какую информацию нужно извлечь из источника или
источников данных. При необходимости, запрос также указывает способ
сортировки, группировки и формирования этих сведений перед
возвращением. Запрос хранится в переменной запроса и инициализируется
выражением запроса. Чтобы упростить написание запросов, в C# появился
новый синтаксис запроса.
// Query #1.
List<int> numbers = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
// Query #2.
var orderingQuery =
from num in numbers
where num < 3 || num > 7
orderby num ascending
select num;
// Query #3.
string[] groupingQuery = { "carrots", "cabbage", "broccoli", "beans",
"barley" };
var queryFoodGroups =
from item in groupingQuery
group item by item[0];
Синтаксис метода
Некоторые операции запросов должны быть выражены в виде вызова метода. Чаще всего
используются методы, возвращающие одноэлементные числовые значения, например
Sum, Max, Min, Average и т.д. Эти методы всегда должны быть вызваны последними в
запросе, поскольку они представляют только одно значение и не могут служить
источником дополнительных действий запроса. В следующем примере демонстрируется
вызов метода в выражении запроса.
List<int> numbers1 = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
List<int> numbers2 = new List<int>() { 15, 14, 11, 13, 19, 18, 16, 17, 12, 10
};
// Query #4.
double average = numbers1.Average();
14
// Query #5.
var concatenationQuery = numbers1.Concat(numbers2);
Если у метода есть параметры, они представлены в виде лямбда-выражения, как показано
в следующем примере.
// Query #6.
var largeNumbersQuery = numbers2.Where(c => c > 15);
// Query #7.
class Customer
15
{public string ID ;
private string City ;
private string Country ;
private string Region ;
private decimal Sales ;
public string Get_Region() { return Region; }
public Customer(string ID, string City, string Country, string Region, decimal
Sales)
{this.ID = ID; this.City = City; this.Country = Country;
this.Region = Region; this.Sales = Sales;}
public string Info()
{ return "ID: " + ID + " Город: " + City + " Страна: " + Country +
"Регион: " + Region + " Продажи: " + Convert.ToString(Sales); } }
16
Рис. 43. Форма для вывода части коллекции
17
В предложении where может содержаться один или несколько методов,
возвращающих логические значения.
Например,
var queryEvenNums =from num in numbers where IsEven(num)select num;
// Выполнение запроса
foreach (var s in queryEvenNums)
{Console.Write(s.ToString() + " "); } }
// Метод.
static bool IsEven(int i)
{ return i % 2 == 0; }
18
Например, поместим на форму кнопки для определения того, что есть
заказчики из США и из Азии.
Код, выполняемый при нажатии на ту и другую кнопки, следующий:
private void button2_Click(object sender, EventArgs e)
{ bool anyUSA = customers.Any(с => с.Get_Country() == "USA");
if (anyUSA)
label1.Text = "Некоторые заказчики находятся в США";
else
label1.Text = "Нет заказчиков из США"; }
Групповой запрос
Групповой запрос делит данные на группы и позволяет сортировать,
вычислять агрегатные значения и сравнивать группы.
В код события нажатия кнопки Сумма заказов по каждому региону поместим
два запроса и цикл обработки результатов:
var queryResults =
from с in customers group с by с.Get_Region() into eg
select new { TotalSales = eg.Sum(c => c.Get_Sales()), Region = eg.Key };
var orderedResults =
from eg in queryResults
orderby eg.TotalSales descending
select eg;
foreach (var item in orderedResults)
{listBox2.Items.Add(item.TotalSales + "\t: " + item.Region);
Данные в групповом запросе группируются по ключевому полю —
полю, для которого все члены каждой группы имеют одноименное значение
– сумма продаж. В этом примере ключевым полем является Region:
group с by с.Get_Region()
Необходимо вычислить сумму по каждой группе, поэтому выполняется
группирование в новый результирующий набор по имени eg:
group с by с.Get_Region() into eg
В конструкции select определяются новые поля — общая сумма продаж
(вычисляемая путем сылки на результирующий набору eg) и ключевое
значение группы, к которому обращение происходит по специальному полю
Key группы:
select new { TotalSales = eg.Sum(c => с. Get_Sales()), Region =
eg.Key }.это критерий создания каждой группы данных.
19
Желательно упорядочить результат в порядке убывания по полю
TotalSales. Для этого создается второй запрос для упорядочивания
результатов группового запроса. Это стандартный запрос select с
конструкцией orderby; он не использует никаких групповых средств LINQ, за
исключением того, что источник данных для него поступает от предыдущего
группового запроса.
Затем результаты второго запроса выводятся в список.
Вложенная группировка
20
DataClass.Student Level = FirstYear
Names that begin with: Feng
Feng Hanying
Names that begin with: Mortensen
Mortensen Sven
Names that begin with: Tucker
Tucker Michael
DataClass.Student Level = FourthYear
Names that begin with: Garcia
Garcia Cesar
Names that begin with: O'Donnell
O'Donnell Claire
Names that begin with: Zabokritski
Zabokritski Eugene
*/
Take и Skip
В ряде случаев нужно найти несколько первых данных из запроса. Их
количество заранее неизвестно, поэтому нельзя использовать условие where
для их поиска.
LINQ-операция такого запроса представлена методом Take (), который
учитывает первые n результатов при выводе запроса. При практическом
применении это может быть скомбинировано с orderby для получения первых
n результатов.
Противоположностью Take () является метод Skip (), который
пропускает первые n результатов, возвращая остальные.
Предположим, что добавлено две кнопки – выбор первого десятка
продаж с наибольшими суммами и выдача всех продаж, кроме первого
десятка.
Запрос:
var queryResults =
from c in customers
orderby c.Get_Sales() descending select new {Dan=c.Info()};
Опишем два цикла обработки результатов, один с использованием Take
(), а другой — с применением Skip ():
foreach (var item in queryResults.Take(10))
{ listBox2.Items.Add(item.Dan); }
foreach (var item in queryResults.Skip(10))
{ listBox2.Items.Add(item.Dan);}
First и FirstOrDefault
Предположим, что требуется найти заказчика из Африки в наборе
данных.
LINQ предоставляет эту возможность через метод First(), который
возвращает первый элемент результирующего набора, отвечающий заданным
критериям. Если нет ни одного заказчика, например, из Антарктиды, то LINQ
21
предоставляет метод для обработки такого случая без дополнительного кода
обработки ошибок: FirstOrDefault():
var queryResults = from c in customers
select new{ID=c.Get_ID(),Region=c.Get_Region()} ;
listBox1.Items.Add(queryResults.First(c => c.Region == "Africa"));
listBox1.Items.Add(queryResults.FirstOrDefault(c => c.Region ==
"Antarctica"));
Операции с множествами
В LINQ операциями с множествами называют операции запроса,
образующие результирующий набор, основанный на наличии или отсутствии
эквивалентных элементов внутри одной или разных коллекций (или
множеств).
В следующем разделе перечислены методы стандартных операторов
запросов, выполняющие операции с множествами.
Имя
Описание
метода
Distinct
На следующем рисунке показано действие метода Distinct в
последовательности знаков. Возвращаемая последовательность содержит
уникальные элементы из входной последовательности.
Except
На следующем рисунке показано действие метода Except. Возвращаемая
последовательность содержит только те элементы из первой входной
22
последовательности, которые не содержатся во второй входной
последовательности.
Intersect
На следующем рисунке показано действие метода Intersect. Возвращаемая
последовательность содержит элементы, общие для обеих входных
последовательностей.
Union
На следующем рисунке показана операция объединения двух
последовательностей знаков. Возвращаемая последовательность содержит
уникальные элементы из обеих входных последовательностей.
23
orders.Add(new Order("P", 100 ));
orders.Add(new Order ("Q", 200 ));
orders.Add(new Order ("R",300));
orders.Add(new Order ("S",400));
orders.Add(new Order ("T",500));
orders.Add(new Order ("MU", 600));
orders.Add(new Order ("V",700));
orders.Add(new Order ("MW",800));
orders.Add(new Order ("X",900));
orders.Add(new Order ("Y",1000));
orders.Add(new Order ("Z",1100));
Создадим запросы по каждой коллекции:
var customerlDs =
from с in customers
select с.Get_ID();
var orderlDs =
from o in orders
select o.Get_ID();
Далее создадим три запроса для выполнения соответственно операций
пересечения, исключения и объединения:
var customersWithOrders = customerlDs.Intersect(orderlDs);
listBox1.Items.Clear();
foreach (var item in customersWithOrders)
{listBox1.Items.Add(item); }
Соединения
Наборы данных, подобные спискам customers и orders, которые были
только что созданы с общим ключевым полем (ID) позволяют использовать
запрос join, посредством которого можно запросить взаимосвязанные
данные из обоих списков в единственном запросе, объединяя их по значению
ключевого поля.
var queryResults =
from c in customers
join o in orders on c.Get_ID() equals o.Get_ID()
24
select new { ID=c.Get_ID(), City=c.Get_City(), SalesBefore = c.Get_Sales(),
NewOrder = o.Get_Amount(), SalesAfter = c.Get_Sales()+o.Get_Amount() };
listBox1.Items.Clear();
foreach (var item in queryResults)
{listBox1.Items.Add(item.ID+" "+item.City+"
"+Convert.ToString(item.SalesBefore)+" "
+Convert.ToString(item.NewOrder)+" "+Convert.ToString(item.SalesAfter));}
Операнды equals – это сравниваемые значения ключа в двух списках.
Вид формы при выполнении и нажатии кнопки Соединение (рис. 45):
var queryFirstLetters =
from student in students
group student by student.LastName[0];
C#
var queryNumericRange =
from student in students
let percentile = GetPercentile(student)
group new { student.FirstName, student.LastName } by percentile into
percentGroup
30
orderby percentGroup.Key
select percentGroup;
31
Вставьте приведенный ниже метод в класс StudentClass. Измените оператор
вызова в методе Main на sc.GroupByBoolean().
C#
var queryHighScoreGroups =
from student in students
group student by new { FirstLetter = student.LastName[0],
Score = student.ExamScores[0] > 85 } into studentGroup
orderby studentGroup.Key.FirstLetter
select studentGroup;
Пример
C#
Копировать
class Person
{
public string FirstName { get; set; }
34
public string LastName { get; set; }
}
class Pet
{
public string Name { get; set; }
public Person Owner { get; set; }
}
/// <summary>
/// Simple inner join.
/// </summary>
public static void InnerJoinExample()
{
Person magnus = new Person { FirstName = "Magnus", LastName =
"Hedlund" };
Person terry = new Person { FirstName = "Terry", LastName =
"Adams" };
Person charlotte = new Person { FirstName = "Charlotte", LastName
= "Weiss" };
Person arlene = new Person { FirstName = "Arlene", LastName =
"Huff" };
Person rui = new Person { FirstName = "Rui", LastName =
"Raposo" };
35
Обратите внимание, что объект Person,свойство которого LastName имеет значение
"Huff", не отображается среди результатов, так как не существует объекта Pet, свойство
Pet.Owner которого было бы равно свойству Person.
C#
Копировать
class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int EmployeeID { get; set; }
}
class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int StudentID { get; set; }
}
/// <summary>
/// Performs a join operation using a composite key.
/// </summary>
public static void CompositeKeyJoinExample()
{
// Create a list of employees.
List<Employee> employees = new List<Employee> {
new Employee { FirstName = "Terry", LastName = "Adams",
EmployeeID = 522459 },
new Employee { FirstName = "Charlotte", LastName = "Weiss",
EmployeeID = 204467 },
new Employee { FirstName = "Magnus", LastName = "Hedland",
EmployeeID = 866200 },
new Employee { FirstName = "Vernette", LastName = "Price",
EmployeeID = 437139 } };
C#
Копировать
class Person
{
37
public string FirstName { get; set; }
public string LastName { get; set; }
}
class Pet
{
public string Name { get; set; }
public Person Owner { get; set; }
}
// The first join matches Person and Cat.Owner from the list of
people and
// cats, based on a common Person. The second join matches dogs
whose names start
// with the same letter as the cats that have the same owner.
var query = from person in people
join cat in cats on person equals cat.Owner
join dog in dogs on
38
new { Owner = person, Letter = cat.Name.Substring(0,
1) }
equals new { dog.Owner, Letter =
dog.Name.Substring(0, 1) }
select new { CatName = cat.Name, DogName =
dog.Name };
C#
Копировать
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
class Pet
{
public string Name { get; set; }
39
public Person Owner { get; set; }
}
/// <summary>
/// Performs an inner join by using GroupJoin().
/// </summary>
public static void InnerGroupJoinExample()
{
Person magnus = new Person { FirstName = "Magnus", LastName =
"Hedlund" };
Person terry = new Person { FirstName = "Terry", LastName =
"Adams" };
Person charlotte = new Person { FirstName = "Charlotte", LastName
= "Weiss" };
Person arlene = new Person { FirstName = "Arlene", LastName =
"Huff" };
40
// Terry - Boots
// Terry - Blue Moon
// Charlotte - Whiskers
41