Я думаю многим читателям блога .Net знакомо имя John Skeet. Особенно после вчерашнего поста юзера SergeyT. Поэтому я не буду повторять про сравнение с Чаком Норрисом и первое место по карме на StackOverflow.com. А вот упомянуть лишний раз про его замечательную книгу “C# In Depth” точно лишним не будет. Центральное место в ней занимает LINQ вообще и LINQ to Objects в частности. Джон очень обстоятельно описывает все возможности языка C# и платформы .Net, которые сделали возможным появление LINQ в его нынешнем виде, а также подробности его реализации. Именно после прочтения этой книги я стал активно использовать LINQ to Objects в своих проектах. Однако в стандартной библиотеке не хватает нескольких крайне нужных операторов. К счастью, Джон Скит исправил это недоразумение. Так появилась небольшая, но очень полезная библиотка morelinq. А с конца прошлого года она доступна в виде NuGet-пакета.
Операторы библиотеки morelinq
Batch | Превращает одну последовательность в несколько последовательностей по n элементов. |
Concat | Присоединяет элемент к коллекции либо коллекцию к элементу. |
Consume | «Поглощает» коллекцию, не производя никаких действий над элементами. |
DistinctBy | Возвращает только уникальные элементы (по заданному критерию). |
EquiZip | Создает новую последовательность, где каждый элемент создается на основе соответствующих элементов исходных последовательностей. Если последовательности имеют различное количество элементов, будет брошено исключение InvalidOperationException. |
ExceptBy | Возвращает элементы первой последовательности, которые не содержатся во второй (по заданному критерию). |
ForEach | Выполняет действие над каждым элементом последовательности. |
Generate | Генерирует последовательности по начальному элементу и функции-генератору. |
GenerateByIndex | Генерирует последовательность по индексам элементов. |
GroupAdjacent | Подобен GroupBy, но в группу попадают только идущие подряд элементы. |
Index | Возвращает последовательность пар индекс-значение. |
MaxBy | Возвращает максимальный элемент последовательности по заданному критерию. |
MinBy | Возвращает минимальный элемент последовательности по заданному критерию. |
Pad | Если количество элементов последовательности меньше заданного, дополняет последовательность значениями по умолчанию до заданного количества. |
Pairwise | Возвращает последовательность результатов функции текущего и предыдущего элемента (не применяется к первому элементу). |
Pipe | Возвращает исходную последовательность, выполняя Action над каждым элементом. |
Prepend | Дополняет начало коллекции заданным элементом. |
PreScan | Возвращает последовательность исходной длины, в которой N-й элемент определяется применением заданного преобразования к N-1 элементов. |
Scan | Возвращает последовательность исходной длины, в которой N-й элемент определяется применением заданного преобразования к N элементов. |
SingleOrFallback | Возвращает единственный элемент последовательности либо результат заданного делегата, если последовательность пуста. |
SkipUntil | Пропускает элементы исходной последовательности, пока заданное условие не станет истинным. Текущий элемент будет последним пропущенным. |
Split | Разделяет последовательность заданным разделителем (возвращает последовательность последовательностей). |
TakeEvery | Возвращает каждый N-й элемент исходной последовательности. |
TakeLast | Возвращает последние N элементов исходной последовательности. |
TakeUntil | Возвращает элементы исходной последовательности, пока заданное условие не станет истинным. Текущий элемент будет последним возвращенным. |
ToDataTable | Позволяет преобразовать последовательность в новую DataTable или заполнить имеющуюся. Есть возможность задать лямдами получение из исходного элемента значений для полей таблицы. |
ToDelimitedString | Преобразует последовательность в строку с разделителями (то что обычно приходится делать через нудный Aggregate). |
ToHashSet | Возвращает HashSet〈T&кang; от исходных элементов. |
Zip | То же, что EquiZip, но длина результирующей последовательности будет равна длине наименьшей из исходных. |
ZipLongest | То же, что EquiZip, но длина результирующей последовательности будет равна длине наибольшей из исходных (в качестве недостающих значений будет использовано значение по умолчанию). |
Большинство операторов перегружены для большей гибкости использования (например, можно задать свой IComparer и т.п.). Кроме перечисленных операторов, имеются еще два отладочных – AssertCount (проверяют количество элементов последовательности) и Trace (выводит все элементы в debug-консоль).
Вместе с исходниками библиотеки идет прекрасная документация в стиле MSDN, в которой подробно описаны все операторы, их параметры и имеются примеры использования. Также есть комментарии в исходном коде.
В заключение хочу обратить внимание читателей на две другие библиотеки авторства Джона Скита – MiscUtils и NodaTime (NuGet Package). Особенно интересна последняя – библиотека предназначена для работы с датой/временем. Джон занимался ей последние несколько лет и в ноябре прошлого года наконец выпустил версию 1.0. В его блоге можно почитать много интересного на тему того, чем плохи для этих целей стандартные классы .Net и какие подводные грабли поджидают разработчика, серьезно работающего со временем.
Автор: m_a_d