Как отметил Даниэль в комментарии, ключевой вопрос заключается в том, насколько лучше нужно сравнивать производительность с решением, основанным на стандартной функции Seq.groupBy
?Если вам нужно обработать много данных, на самом деле для этой цели может быть проще использовать какую-то базу данных.
Если вам нужно что-то в ~ 1,7 раза быстрее (или, возможно, больше, в зависимости от количества ядер):-)), тогда вы можете попробовать заменить Seq.groupBy
на параллельную версию на основе Parallel LINQ, которая доступна в F # PowerPack.Используя PSeq.groupBy
(и другие PSeq
функции), вы можете написать что-то вроде этого:
#r "FSharp.PowerPack.Parallel.Seq.dll"
open Microsoft.FSharp.Collections
// Takes a collection of events and merges prices of events with the same name/hour
let mergeEvents (events:seq<event>) =
events
|> PSeq.groupBy (fun evt -> evt.Name, evt.Hour)
|> PSeq.map (fun ((name, hour), events) ->
// Merge prices of all events in the group with the same Selections.Name
let selections =
events
|> PSeq.collect (fun evt -> evt.Selections)
|> PSeq.groupBy (fun sel -> sel.Name)
|> PSeq.map (fun (name, sels) ->
{ Name = name
Prices = sels |> Seq.collect (fun s -> s.Prices) |> List.ofSeq } )
|> PSeq.toList
// Build new Event as the result - since we're grouping just using
// name & hour, I'm using the first available 'Sport' value
// (which may not make sense)
{ Name = name
Hour = hour
Sport = (Seq.head events).Sport
Selections = selections })
|> PSeq.toList
Я не тестировал производительность этой версии, но считаю, что она должна быть быстрее.Вам также не нужно ссылаться на всю сборку - вы можете просто скопировать исходный код для нескольких соответствующих функций из Исходный код PowerPack .В прошлый раз, когда я проверял, производительность была лучше, когда функции были помечены как inline
, чего нет в текущем исходном коде, так что вы можете проверить это тоже.