Programming Taskbook 0


Download 1.62 Mb.
Pdf ko'rish
bet49/71
Sana21.06.2023
Hajmi1.62 Mb.
#1644761
TuriУчебное пособие
1   ...   45   46   47   48   49   50   51   52   ...   71
Bog'liq
Abramyan-Pascal2016-1


Глава 4. Запросы 
79 
ся число) и возвращая последовательность пар чисел (каждая пара пред-
ставляется в виде кортежа): 
var res := a1.Join(a2, e1 -> e1 mod 10, e2 -> e2 mod 10,
(e1, e2) -> (e1, e2));
Write(res); // [(10,40),(10,60),(21,51),(33,53)] 
Если мы заменим в предыдущем фрагменте имя запроса на GroupJoin, 
не меняя его параметры, то мы тоже получим последовательность пар, но 
теперь вторым элементом каждой пары будет последовательность (всех 
элементов a2, имеющих одинаковый ключ с первым элементом этой же 
пары): 
var res := a1.GroupJoin(a2, e1 -> e1 mod 10, e2 -> e2 mod 10,
(e1, e2) -> (e1, e2));
Write(res); // [(10,[40,60]),(21,[51]),(33,[53]),(84,[])] 
Мы видим, что в данном случае второе поле каждого кортежа является 
последовательностью. Обратите внимание на то, что с элементом 84 свя-
зывается пустая последовательность, поскольку в последовательности a2 
отсутствуют числа, оканчивающиеся на 4 (по этой же причине элемент 84 
отсутствовал в последовательности, построенной с помощью запроса Join). 
Итак, запрос Join формирует «плоское» внутреннее объединение 
(с каждым элементом внешней последовательности в полученном объеди-
нении связывается по одному элементу внутренней), тогда как внешнее 
объединение, формируемое запросом GroupJoin, является иерархическим 
(с каждым элементом внешней последовательности связывается последо-
вательность элементов внутренней). В некоторых ситуациях требуется 
сформировать плоское левое внешнее объединение, которое отличается от 
внутреннего объединения только тем, что включает все элементы внешней 
последовательности — в том числе и те, для которых не нашлось пары во 
внутренней последовательности (подобные элементы в плоском левом 
внешнем объединении объединяются в пару с каким-либо особым значе-
нием, например нулем). 
Поскольку для преобразования иерархической последовательности в 
плоскую предназначен запрос SelectMany, естественно использовать для по-
строения плоского левого внешнего объединения комбинацию запросов 
GroupJoin и SelectMany: 
var res := a1.GroupJoin(a2, e1 -> e1 mod 10, e2 -> e2 mod 10,
(e1, e2) -> e2.Select(e -> (e1, e))).SelectMany(e -> e);
Здесь в последнем лямбда-выражении запроса GroupJoin мы преобразу-
ем последовательность e2 (напомним, что в нее входят все элементы внут-
ренней последовательности, имеющие одинаковый ключ с элементом e1) в 
последовательность пар (e1, e), где e пробегает все элементы последова-
тельности e2, после чего превращаем набор преобразованных последова-


80 
тельностей (т. е. иерархическую последовательность) в плоскую последо-
вательность, используя запрос SelectMany(e -> e). 
Однако в результате мы получим обычное внутреннее объединение: 
Write(res); // [(10,40),(10,60),(21,51),(33,53)] 
Это вполне естественно, поскольку мы не предусмотрели обработку 
особой ситуации: когда с элементом e1 внешней последовательности нель-
зя связать ни одного элемента внутренней последовательности и, таким 
образом, в последнем лямбда-выражении запроса GroupJoin последователь-
ность e2 оказывается пустой. Как мы знаем, запрос SelectMany просто игно-
рирует пустые последовательности. 
Для правильной обработки этой особой ситуации нам было бы доста-
точно «превратить» пустую последовательность e2 в одноэлементную по-
следовательность, содержащую то особое значение, которое в результиру-
ющем плоском левом внешнем объединении мы хотим связать с «одино-
кими» элементами внешней последовательности (в нашем случае таким 
одиноким элементом является число 84).
В стандартной библиотеке платформы .NET предусмотрен запрос, De-
faultIfEmpty специально предназначенный для решения подобных задач.

Download 1.62 Mb.

Do'stlaringiz bilan baham:
1   ...   45   46   47   48   49   50   51   52   ...   71




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling