После поиска довольно много, я не смог найти эквивалент F # Enumerable.DefaultIfEmpty.Есть ли эквивалент F # Enumerable.DefaultIfEmpty?
Что-то подобное существует в F # (возможно, в другом, идиоматическом смысле)?
После поиска довольно много, я не смог найти эквивалент F # Enumerable.DefaultIfEmpty.Есть ли эквивалент F # Enumerable.DefaultIfEmpty?
Что-то подобное существует в F # (возможно, в другом, идиоматическом смысле)?
Seq
функция модуль работает и возвращает IEnumerable<_>
'S и DefaultIfEmpty
работать и возвращать IEnumerable<_>
' с. Как насчет просто обернуть его в функцию, которая является составной.
let inline DefaultIfEmpty d l = System.Linq.Enumerable.DefaultIfEmpty(l, d)
Это также сохраняет лень.
пример:
Seq.empty |> DefaultIfEmpty 0
Update
Я сделал библиотеку с открытым исходным кодом встраивание много расширений и статические методы, в том числе Enumerable.defaultIfEmpty
- ComposableExtesions
Есть несколько вариантов:
DefaultIfEmpty
, которые могут быть не идиоматическое, но будет работатьнаписать свой собственный вот так:
let DefaultIfEmpty (l:'t seq) (d:'t) =
match Seq.length l with |0 -> seq [d] |_ -> l
Беспокойства о бесконечных последовательностей
let DefaultIfEmpty (l:'t seq) (d:'t) =
match Seq.isEmpty l with |true -> seq [d] |false -> l
Чтобы сохранить ленивость последовательности, мы могли бы работать с состоянием перечислителя.
let DefaultIfEmpty (l:'t seq) (d:'t) =
seq{
use en = l.GetEnumerator()
if en.MoveNext() then
yield en.Current
while en.MoveNext() do
yield en.Current
else
yield d }
Я уверен, что 'use' должен находиться внутри блока' seq {} ', иначе перечислитель будет создан с нетерпением и утилизирован слишком рано. – kvb
@kvb Так много для луча в моем собственном глазу. Исправлена. – kaefer
Спасибо за ваш ответ! Предоставленный код работает. Однако, поскольку Stack Overflow позволяет мне выбрать только один правильный ответ, мне пришлось выбрать тот, который я использовал. Еще раз спасибо за ваш ответ! –
Спасибо за ваш ответ!Я закончил использование этого кода, поскольку он компактный, метод доступен по умолчанию, и я могу использовать его без «открытия пространства имен System.Linq». Кроме того, я верю, что реализация BCL 'DefaultIfEmpty' тестируется против (большинства/всех) возможных сценариев. Использование функции в качестве декоратора выглядит как хорошая техника (и я думаю, что это довольно идиоматично). Еще раз спасибо за ваш ответ. –
Учитывая, что это просто оболочка, я думаю, было бы разумно отметить ее как встроенную. – ildjarn