Reputation: 1222
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
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:
m2
will overwrite those in m1
Upvotes: 0
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
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
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