Programming Taskbook 0
Download 1.62 Mb. Pdf ko'rish
|
Abramyan-Pascal2016-1
- Bu sahifa navigatsiya:
- LinqBegin2
- LinqBegin9
- LinqBegin15
Глава 4. Запросы 65 При решении задачи мы использовали запросы First и Last с парамет- рами-предикатами. Поскольку для исходной последовательности требова- лось вызвать два запроса, пришлось связать с ней идентификатор a. Замечание. Полезно напомнить, что произошло бы, если бы послед- ний оператор был включен в «обычную» программу, не связанную с за- дачником, в которой последовательность a вводится с помощью одного из вариантов функции ReadSeqInteger, входящих в стандартную библиотеку PascalABC.NET (например, ReadSeqInteger(10)). В этом случае потребова- лось бы дважды вводить элементы исходной последовательности с клави- атуры — при выполнении каждого из использованных в последнем опера- торе запросов. Чтобы подобные проблемы при выполнении заданий не возникали (и не приводили к сообщениям вида «Попытка ввода лишних исходных данных»), функции ввода последовательностей в модуле PT4 бы- ли специальным образом модифицированы (см. последнее замечание в п. 3.7). В задаче LinqBegin2 дается цифра d и целочисленная последователь- ность. Требуется вывести первый положительный элемент, оканчиваю- щийся цифрой d, или число 0, если таких элементов в последовательности нет: Task('LinqBegin2'); var d := ReadInteger; Write(ReadSeqInteger.FirstOrDefault(e -> (e > 0) and (e mod 10 = d))); В данном случае, поскольку требуемый элемент может отсутствовать, необходимо использовать запрос с суффиксом OrDefault. Мы не стали свя- зывать введенную последовательность с переменной, сразу применив к функции ReadSeqInteger требуемый запрос. В задаче LinqBegin9 требуется вывести минимальный положительный элемент целочисленной последовательности или число 0, если последова- тельность не содержит положительных элементов. Один из очевидных вариантов решения этой задачи — предваритель- ная фильтрация исходной последовательности (см. следующий пункт), однако можно обойтись и теми средствами, которые описаны в данном пункте. Придется лишь дополнительно проанализировать результат, воз- вращенный запросом: Task('LinqBegin9'); var a := ReadSeqInteger.Min(e -> e <= 0 ? integer.MaxValue : e); Write(a = integer.MaxValue ? 0 : a); В запросе Min мы использовали селектор, который сохраняет неизмен- ными все положительные элементы последовательности, а отрицательные заменяет на максимальное значение типа integer (доступное в виде свойства 66 integer.MaxValue). Для этого мы использовали в селекторе тернарную опе- рацию вида условие ? значение1 : значение2, которая вычисляет условие и возвращает значение1, если условие истинно, и значение2, если условие ложно (синтаксис тернарной операции заимствован языком Pascal- ABC.NET из языков семейства C). Если в последовательности имеется хотя бы один положительный элемент, то запрос Min вернет минимальный из таких элементов, а если по- ложительных элементов в последовательности нет, то будет возвращено значение integer.MaxValue. В этом особом случае программа выводит число 0 (еще раз используя тернарную операцию). В задании LinqBegin15 требуется вычислить факториал N! целого числа N (равный произведению всех целых чисел от 1 до N: N! = 12…N), используя генератор Range (описанный в начале п. 3.5) и запрос Aggregate. При этом факториал требуется вычислять в виде вещественного числа, чтобы избежать целочисленного переполнения для больших значений N: Task('LinqBegin15'); Write(Range(1, ReadInteger).Aggregate(1.0, (a, e) -> a * e)); Главной особенностью этого решения является использование второго из вариантов запроса Aggregate, в котором указывается начальное значение аккумулятора в виде 1.0 (т. е. вещественной единицы). Заметим, что запрос Aggregate((a, e) -> a * e) тоже позволяет правильно вычислять факториал (в виде целого числа), но только в ситуации, когда значение факториала не превосходит максимального значения для типа integer (в противном случае из-за целочисленного переполнения будет получено неверное число, кото- рое, в частности, может оказаться отрицательным). 4.2. Фильтрация, сортировка, комбинирование и расщепление В данном пункте мы рассмотрим запросы, позволяющие извлекать из исходной последовательности требуемые элементы (фильтрация), изме- нять порядок следования элементов (сортировка и инвертирование), объ- единять элементы нескольких последовательностей в одну и, наоборот, расщеплять исходную последовательность на две. Все запросы этих групп возвращают новые последовательности (или кортежи из двух последовательностей), тип элементов которых совпадает с типом элементов исходных последовательностей. Как и все запросы, воз- вращающие последовательности, они характеризуются «отложенным» вы- полнением: реальное формирование элементов полученных последова- тельностей будет происходить только при последующем переборе этих элементов (в цикле foreach, при печати или при преобразовании последова- |
Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling
ma'muriyatiga murojaat qiling