Ответ 1
Как упоминал Даниил в комментарии, ключевым вопросом является то, насколько лучше сравнивать производительность с решением на основе стандартной функции 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
, что не соответствует текущему исходному коду, поэтому вы можете также проверить это.