В F #, Как вы объедините 2 экземпляра Collections.Map?

Я пытаюсь объединить два Карты, но нет встроенного метода для объединения коллекций. Итак, как вы это делаете?

Ответ 1

Определите следующую функцию:

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

Пример:

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

и результат:

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

Ответ 2

Вы можете реализовать это с помощью Map.fold и Map.add, так как add фактически добавляет/заменяет:

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 

Вероятно, причина слияния не предоставляется из коробки, так это то, что вам нужно иметь дело с ключевыми конфликтами. В этом простом алгоритме слияния мы просто берем пару ключевых значений из второй карты, это может быть не поведение, которое вы хотите.

Ответ 3

Альтернативный способ:

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

Это позволяет вам определить, какое значение вы хотите, если есть дубликаты ключей.

Пример:

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)]

Обратите внимание, что клавиша 3 отличается.