F# - performing non-deterministic groupings on lists -
i’m working on problem know can solve c#. prove boss f# able solve in more succinct way. understanding of functional programming still immature.
the problem:
i’m working list of ‘trade’ classes. definition of class follows:
type trade(brokerid : string, productid : string, marketid : string, buysideid : string, tradedate : string, ruleid : int) = class member this.brokerid = brokerid member this.productid = productid member this.marketid = marketid member this.buysideid = buysideid member this.tradedate = tradedate end
i need able group trades , apply rule each of resulting groups of data.
however cannot guarantee grouping of data i.e. rule determining grouping potentially change every time program run - instance may have group by:
- tradedate, brokerid
- tradedate only
- tradedate, brokerid, accountid
... , on.
once have distinct groups easy (i think) apply rule (such ‘is total tradeamount greater 10,000’).
any / pointers creating functional orientated solution problem welcome.
many thanks.
if understand problem correctly, want call seq.groupby
function. problem don't quite know lambda function want pass argument when writing code, because function may vary depending on choice of keys should used grouping. here 1 relatively simple way this...
we'll create dictionary of functions gives function reading specified property of trade
(this be, in principle, constructed automatically, easier write it):
let keyfunctions : idictionary<string, trade -> obj> = dict [ "tradedate", (fun t -> box t.tradedate); "brokerid", (fun t -> box t.brokerid); "marketid", (fun t -> box t.marketid); ]
now, if wanted use multiple keys, need way combine 2 functions give parts of key single function. can write combinator takes 2 functions , returns single 1 produces boxed tuple key:
let combine f1 f2 = (fun t -> box (f1 t, f2 t))
if have list of strings specifies keys, need pick function dictionary each of keys , combine them single function using combine
:
let grouping = [ "tradedate"; "marketid" ] let func = grouping |> seq.map (fun n -> keyfunctions.[n]) |> seq.reduce combine
and have function can used argument seq.groupby
:
trades |> seq.groupby func
there other ways in f#, think relatively simple approach convince boss :-). side-note, write same thing in c# 3.0, although bit uglier due more heavy syntax...
edit 1: nice thing approach don't need use reflection. runs compiled code, should pretty efficient. composed function calls several other functions (.net methods) , boxes returned values...
edit 2: regarding order - approach work (when comparing tuples, first elements compared first), i'm not entirely sure in order items aggregated when using seq.reduce
, maybe example works other way round...
Comments
Post a Comment