C# 4.0 полное руководство - 2011
Шрифт:
содержащий пару символов, которые сохраняются в переменных chi и ch2 на каждом шаге циклического обращения к массиву во внутреннем операторе from. А в конечном итоге получается объект типа ChrPair, содержащий все возможные сочетания извлекаемых символов.
Вложенные'операторы from применяются также для циклического обращения к источнику данных, который содержится в другом источнике данных. Соответствующий пример приведен в разделе "Применение оператора let для создания временной переменной в запросе" далее в этой главе.
Группирование результатов с помощью оператора group
Одним
group переменная_диапазона by ключ
Этот оператор возвращает данные, сгруппированные в последовательности, причем каждую последовательность обозначает общий ключ.
Результатом выполнения оператора group является последовательность, состоящая из элементов типа IGrouping<TKey, TElement>, т.е. обобщенного интерфейса, объявляемого в пространстве имен System. Linq. В этом интерфейсе определена коллекция объектов с общим ключом. Типом переменной запроса, возвращающего группу, является IEnumerable<IGrouping<TKey, TElement>>. В интерфейсе IGrouping определено также доступное только для чтения свойство Key, возвращающее ключ, связанный с каждой коллекцией.
Ниже приведен пример, демонстрирующий применение оператора group. В коде этого примера сначала объявляется массив, содержащий список веб-сайтов, а затем формируется запрос, в котором этот список группируется по имени домена самого верхнего уровня, например . org или . сот.
// Продемонстрировать применение оператора group.
using System; using System.Linq;
class GroupDemo {
static void Main {
string[] websites = { "hsNameA.com", "hsNameB.net", "hsNameC.net", "hsNameD.com", "hsNameE.org", "hsNameF.org",
"hsNameG.tv", "hsNameH.net", "hsNamel.tv"
};
// Сформировать запрос на получение списка веб-сайтов,
// группируемых по имени домена самого верхнего уровня.
var webAddrs = from addr in websites
where addr.LastlndexOf('.') != -1
group addr by addr.Substring(addr.LastlndexOf('.'));
// Выполнить запрос и вывести его результаты, foreach(var sites in webAddrs) {
Console.WriteLine("Веб-сайты, сгруппированные " +
"по имени домена" + sites.Key); foreach(var site in sites)
Console.WriteLine (" " + site);
Console.WriteLine;
}
}
}
Вот к какому результату приводит выполнение этого кода.
Веб-сайты, сгруппированные по имени домена .сот
hsNameA.сот hsNameD.сот
Веб-сайты, сгруппированные по имени домена .net hsNameB.net hsNameC.net
hsNameH.net *
Веб-сайты, сгруппированные по имени домена .org hsNameE.org hsNameF.org
Веб-сайты, сгруппированные по имени домена .tv hsNameG.tv hsNamel.tv
Как следует из приведенного выше результата, данные, получаемые по запросу, группируются по имени домена самого верхнего уровня в адресе веб-сайта. Обратите внимание на то, как это делается в операторе group из следующего запроса.
var webAddrs = from addr in websites
where addr.LastlndexOf('.') != -1
group addr by addr.Substring(addr.LastlndexOf('.'));
Ключ в этом операторе создается с помощью методов LastlndexOf и Substring , определенных для данных типа string. (Эти методы упоминаются в главе 7, посвященной массивам и строкам. Вариант метода Substring , используемый в данном примере, возвращает подстроку, начинающуюся с места, обозначаемого индексом, и продолжающуюся до конца вызывающей строки.) Индекс последней точки в адресе веб-сайта определяется с помощью метода LastlndexOf . По этому индексу в методе Substring создается оставшаяся часть строки, в которой содержится имя домена самого верхнего уровня. Обратите внимание на то, что в операторе where отсеиваются все строки, которые не содержат точку. Метод LastlndexOf возвращает -1, если указанная подстрока не содержится в вызывающей строке.
Последовательность результатов, получаемых при выполнении запроса, хранящегося в переменной webAddrs, представляет собой список групп, поэтому для доступа к каждому члену группы требуются два цикла foreach. Доступ к каждой группе осуществляется во внешнем цикле, а члены внутри группы перечисляются во внутреннем цикле. Переменная шага внешнего цикла foreach должна быть экземпляром интерфейса I Grouping, совместимым с ключом и типом элемента данных. В рассматриваемом здесь примере ключи и элементы данных относятся к типу string. Поэтому переменная sites шага внешнего цикла имеет тип IGrouping<string, string>, а переменная site шага внутреннего цикла — тип string. Ради краткости данного примера обе переменные объявляются неявно, хотя их можно объявить и явным образом, как показано ниже.
foreach(IGrouping<string, string> sites in webAddrs) {
Console.WriteLine("Веб-сайты, сгруппированные " +
"по имени домена" + sites.Key); foreach(string site in sites)
Console.WriteLine(" " + site);
Console.WriteLine ;
}
Продолжение запроса с помощью оператора into
При использовании в запросе оператора select или group иногда требуется сформировать временный результат, который будет служить продолжением запроса для получения окончательного результата. Такое продолжение осуществляется с помощью оператора into в комбинации с оператором select или group. Ниже приведена общая форма оператора into:
into имя тело_запроса
где имя обозначает конкретное имя переменной диапазона, используемой для циклического обращения к временному результату в продолжении запроса, на которое указывает тело_запроса. Когда оператор into используется вместе с оператором select или group, то его называют продолжением запроса, поскольку он продолжает запрос. По существу, продолжение запроса воплощает в себе принцип построения нового запроса по результатам предыдущего.