klactose
klactose

Reputation: 1222

in F#, How do you merge 2 Collections.Map instances?

I am trying to merge two Maps, but there is no built in method for joining Collections. So how do you do it?

Upvotes: 19

Views: 8190

Answers (4)

Christoffer
Christoffer

Reputation: 197

If you prefer using function composition you could define a join function like this:

let join (m1:Map<'a,'b>) (m2:Map<'a,'b>) = 
    Map.foldBack Map.add m2 m1

Given that m1 and m2 are Maps you would then use it like this:

m3 = join m1 m2

Some caveats:

  • Keys in m2 will overwrite those in m1
  • As others have noted it's faster to let the smaller map be the second argument as it will result in fewer insertions

Upvotes: 0

Lasse Espeholt
Lasse Espeholt

Reputation: 17782

An alternative way is this:

let merge (a : Map<'a, 'b>) (b : Map<'a, 'b>) (f : 'a -> 'b * 'b -> 'b) =
    Map.fold (fun s k v ->
        match Map.tryFind k s with
        | Some v' -> Map.add k (f k (v, v')) s
        | None -> Map.add k v s) a b

It lets you decide on what value you want if there is duplicate keys.

Example:

let a = Map([1,11;2,21;3,31;])

let b = Map([3,32; 4,41;5,51;6,61;])

merge a b (fun k (v, v') -> v + v');;

//Result
val it : Map<int,int> =
  map [(1, 11); (2, 21); (3, 63); (4, 41); (5, 51); (6, 61)]

Notice that the key 3 is different.

Upvotes: 15

Yin Zhu
Yin Zhu

Reputation: 17119

Define the following function:

let join (p:Map<'a,'b>) (q:Map<'a,'b>) = 
    Map(Seq.concat [ (Map.toSeq p) ; (Map.toSeq q) ])

example:

let a = Map([1,11;2,21;3,31;])

let b = Map([3,32; 4,41;5,51;6,61;])

let c = join a b

and the result:

val c : Map<int,int> =
  map [(1, 11); (2, 21); (3, 32); (4, 41); (5, 51); (6, 61)]

Upvotes: 10

Robert
Robert

Reputation: 6437

You can implement this using Map.fold and Map.add, since add is actually add/replace:

let map1 = Map.ofList [ 1, "one"; 2, "two"; 3, "three" ]
let map2 = Map.ofList [ 2, "two"; 3, "oranges"; 4, "four" ]


let newMap = Map.fold (fun acc key value -> Map.add key value acc) map1 map2

printfn "%A" newMap 

Probably the reason merge isn't provided out of the box is that you need to deal with key conflicts. In this simple merge algorithm we simple take the key value pair from the second map, this may not be the behaviour you want.

Upvotes: 33

Related Questions