Programming Taskbook 0
Download 1.62 Mb. Pdf ko'rish
|
Abramyan-Pascal2016-1
- Bu sahifa navigatsiya:
- [1,2,1,3,1,4,1,5]
- [121,122,131,133,141,144,151,155]
- [(1,12),(2,13),(3,14),(4,15)]
- [(1,1),(2,1.4142135623731),(3,1.73205080756888),(4,2)]
- LinqBegin33 ); ReadSeqInteger.Where(e -> e > 0) .Select(e -> e mod 10).Distinct.WriteAll; В задаче LinqBegin38
- LinqBegin38 ); // Вариант 1
- LinqBegin38 ); // Вариант 2
Глава 4. Запросы 75 Если же заменить в приведенном фрагменте запрос Select на запрос Se- lectMany, то элементы полученных в лямбда-выражении последовательно- стей запишутся в итоговую последовательность в «плоском» виде: var a := Range(12,15).SelectMany(e -> Seq(e div 10, e mod 10)); Write(a); // [1,2,1,3,1,4,1,5] Имеет смысл проиллюстрировать и применение второго, более слож- ного варианта запроса SelectMany, использующего два селектора. Изменим предыдущий пример так, чтобы в формируемой последовательности со- хранять не отдельную цифру каждого исходного числа, а само исходное число, к которому справа приписана одна из его цифр (например, по числу 12 мы хотим получить два числа: 121 и 122). С применением второго вари- анта запроса SelectMany это можно реализовать следующим образом: var a := Range(12,15).SelectMany(e -> Seq(e div 10, e mod 10), (e, d) -> e * 10 + d); Write(a); // [121,122,131,133,141,144,151,155] Чтобы подчеркнуть, что в обоих селекторах в качестве первого пара- метра используется элемент исходной последовательности, мы выбрали для этих параметров одно и то же имя: e. Второй параметр второго селек- тора является одной из тех цифр, которая была получена при «расщепле- нии» числа e; для этого параметра мы выбрали имя d (от англ. digit — «цифра»). Имеются модификации запросов Select и SelectMany, в которых в каче- стве дополнительного параметра селектора sel можно использовать индекс обрабатываемого элемента исходной последовательности. Напомним, что аналогичная возможность реализована и для ранее рассмотренных запро- сов Where, TakeWhile, SkipWhile и Partition (см. п. 4.2). Запрос Numerate(from) позволяет снабдить элементы исходной последо- вательности нумерацией, начиная от номера from (при отсутствии парамет- ра from он считается равным 1). Полученная последовательность является последовательностью кортежей: var a := Range(12,15).Numerate; Write(a); // [(1,12),(2,13),(3,14),(4,15)] Запрос Tabulate упрощает формирование данных для табуляции функ- ций (которая ранее обсуждалась нами в пунктах 1.3 и 3.5). С его помощью можно сформировать последовательность пар вида (x, f(x)), где аргументы x берутся из исходной последовательности, а функция f является параметром запроса: var a := Range(1,4).Tabulate(x -> Sqrt(x)); Write(a); // [(1,1),(2,1.4142135623731),(3,1.73205080756888),(4,2)] 76 Как обычно, в конце пункта приведем решения нескольких задач группы LinqBegin, иллюстрирующие применение изученных запросов. В задаче LinqBegin33 требуется выделить из исходной целочисленной последовательности положительные числа, извлечь из них последние циф- ры и удалить в полученной последовательности цифр все вхождения оди- наковых цифр, кроме первого, после чего вывести оставшиеся цифры в ис- ходном порядке: Task('LinqBegin33'); ReadSeqInteger.Where(e -> e > 0) .Select(e -> e mod 10).Distinct.WriteAll; В задаче LinqBegin38 требуется обработать элементы исходной цело- численной последовательности следующим образом: если порядковый но- мер элемента делится на 3 (3, 6, …), то этот элемент не включается в но- вую последовательность; если остаток от деления порядкового номера на 3 равен 1 (1, 4, …), то в новую последовательность добавляется удвоенное значение этого элемента; в противном случае (для элементов с номерами 2, 5, …) элемент добавляется в новую последовательность без изменений. При решении этой задачи следует использовать запросы с лямбда- выражением, включающим индекс обрабатываемого элемента; кроме того, надо учитывать, что индекс элемента на 1 меньше его порядкового номера. Если переформулировать условие задачи в терминах индексов, то мы по- лучим, что удваивать надо элементы, индекс которых делится на 3 без остатка, а удалять надо элементы, индекс которых дает при делении на 3 остаток 2. Поскольку при удалении части элементов индексы оставшихся эле- ментов изменятся, следует вначале изменить (удвоить) нужные элементы с помощью запроса Select, а затем выполнить удаление лишних элементов: Task('LinqBegin38'); // Вариант 1 ReadSeqInteger.Select((e, i) -> i mod 3 = 0 ? 2 * e : e) .Where((e, i) -> i mod 3 <> 2).WriteAll; Если воспользоваться тем фактом, что в запросе SelectMany с элемен- том допустимо связывать пустую последовательность, то можно реализо- вать решение задачи LinqBegin38, не требующее применения запроса Where: Task('LinqBegin38'); // Вариант 2 ReadSeqInteger.SelectMany((e, i) -> i mod 3 = 0 ? Seq(2 * e) : i mod 3 = 1 ? Seq(e) : SeqFill(0, 0)).WriteAll; Прокомментируем использованное в запросе лямбда-выражение. Если индекс элемента делится на 3, то возвращается одноэлементная последова- тельность, содержащая удвоенное значение исходного элемента; в против- ном случае, если индекс элемента при делении на 3 дает остаток 1, то воз- |
Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling
ma'muriyatiga murojaat qiling