Агрегатные функции в модуле Seq

Я пытаюсь добавить некоторые дополнительные агрегатные функции в модуль Seq. Я смотрел на реализацию некоторых функций, перечисленных здесь:

https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/seq.fs

Одно из заявлений об отказе от ответственности: «Эта функция возвращает последовательность, которая обрабатывает всю исходную последовательность, как только эта последовательность повторяется. В результате эту функцию не следует использовать с большими или бесконечными последовательностями». Это верно для многих функций, таких как GroupBy.

  • Первый вопрос: существуют ли методы написания агрегатных функций, которые могут эффективно обрабатывать большие последовательности? Я знаю, что «большой» субъективен; Я просто ищу общие шаблоны для написания таких функций.

  • Второй вопрос: как обеспечить эффективную сборку мусора для таких коллекций, как Dictionary (которые определены в агрегатных функциях)? Я понимаю, что словари должны собираться, когда они выходят за рамки, но есть ли способ явно указать это? Учитывая, что область действия словаря остается внутри функции, я не могу вызвать .Clear() для этого, верно?


person Bala    schedule 23.06.2011    source источник
comment
Какой тип агрегации вам нужен, который нельзя реализовать с точки зрения Seq.fold?   -  person ildjarn    schedule 23.06.2011
comment
Как насчет функции SumBy? Что-то вроде Seq‹string * int›, и вы хотели бы сгруппировать по первому столбцу и суммировать по второму.. Вы можете сделать Seq.GroupBy и передать его в Seq.Sum, но это работает плохо..   -  person Bala    schedule 23.06.2011
comment
@ildjarn: Да, это работает для SumBy в одном столбце. На самом деле SumBy встроен, так что работает. Я ищу эквивалент функции CountBy. CountBy группируется по ключу и возвращает количество вхождений каждого ключа. Я хочу сгруппировать по ключу и вернуть сумму другого столбца. Более конкретный пример: предположим, что журнал телефонных звонков содержит столбцы PhoneNo и CallDuration. Я хочу получить PhoneNos с максимальной общей продолжительностью вызова.   -  person Bala    schedule 23.06.2011


Ответы (1)


Чтобы ответить на ваш первый вопрос. В этом случае проблема с большими входными данными заключается в том, что вся последовательность должна быть обработана, прежде чем такие функции, как fold или groupBy, смогут дать результат. Вот несколько вещей, которые вы можете сделать:

  • Используйте такие функции, как Seq.scan, которые агрегируют значения так же, как fold, но возвращают текущее состояние после добавления каждого элемента - результат также является последовательностью, и вы можете лениво использовать ее (и получать, например, все более и более точный результат).

  • При написании функций, возвращающих seq<'a>, вы должны спроектировать их так, чтобы получение следующего элемента из последовательности потребляло только некоторое предсказуемое количество элементов ввода (но не всю входную последовательность). Это невозможно, например. для groupBy, но вы можете написать конструкцию, подобную группировке, которая группирует только соседние элементы одной и той же группы.

Чтобы ответить на второй вопрос - вам вообще не стоит слишком беспокоиться о сборщике мусора. Принудительная сборка мусора в конце функции, вероятно, причинит больше вреда, чем просто полагаться на то, что GC будет работать хорошо.

person Tomas Petricek    schedule 23.06.2011