Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Already existing high-order function for this algorithm?

I've come up with this simple algorithm (convert list of tuples to a map collection of keys to lists) that I needed in my F# code:

let MergeIntoMap<'K,'V when 'K: comparison>(from: seq<'K*'V>): Map<'K,seq<'V>>=
    let keys = from.Select(fun (k,v) -> k)
    let keyValuePairs = seq {
        for key in keys do
            let valsForKey = from.Where(fun (k,v) -> key = k).Select(fun (k,v) -> v) |> seq
            yield key,valsForKey
    }
    keyValuePairs |> Map.ofSeq

Example input:

[ ("a", 1); ("b", 2), ("a", 3) ]

Output:

dict [ ("a", [1; 3]), ("b", [2]) ]

And I was thinking this must be something that is already in the BCL or F#'s set of high order functions maybe? If yes, can someone reference me to it? Because I'm sure my code is not very efficient as it is...

like image 838
ympostor Avatar asked Oct 17 '22 16:10

ympostor


1 Answers

It seems you want to get something like that

let toGroupMap x = 
    x
    |> Seq.groupBy fst 
    |> Seq.map 
        (fun (k,v) -> k, v |> Seq.map snd |> Seq.toArray)
    |> Map.ofSeq

fsi:

val toGroupMap : x:seq<'a * 'b> -> Map<'a,'b []> when 'a : comparison
val input : (string * int) list = [("a", 1); ("b", 2); ("a", 3)]
val output : Map<string,int []> = map [("a", [|1; 3|]); ("b", [|2|])]

Edit

As written Fyodor Soikin in the comments, there is a extension method ToLookup, which probably does what you need.

open System.Linq

let output = input.ToLookup(fst, snd)

You can read here about the difference between ILookup and IDictionary interfaces

like image 124
FoggyFinder Avatar answered Oct 21 '22 09:10

FoggyFinder