2010-10-20 12 views
10

Sto cercando di unire due mappe, ma non esiste un metodo integrato per unire le raccolte. Quindi come lo fai?in F #, come si uniscono due istanze Collections.Map?

+0

si dovrebbe guardare qui (http://stackoverflow.com/questions/590991/merging-two-ienumerablets), in pratica map1.Union (map2) dovrebbe funzionare – dvhh

+0

Debole cavillo: utilizzando l'operatore Union di linq si finirebbe con un IEnumerable di tuple, non proprio la stessa di una mappa. – Robert

risposta

6

Definire la seguente funzione:

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

esempio:

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 

e il risultato:

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

Grazie! Questo funziona. – klactose

+1

Attenzione, questo ricostruisce da zero sia le mappe che possono essere molto lente. Una soluzione migliore è quella di Robert se 'map1' è grande e' map2' è piccolo. –

20

È possibile implementare questo utilizzando Map.fold e Map.add, dato aggiuntivo è in realtà aggiungere/sostituire:

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 

Probabilmente il motivo di unione non è prevista fuori dalla scatola è che è necessario affrontare con conflitti chiave. In questo semplice algoritmo di fusione, prendiamo semplicemente la coppia di valori chiave dalla seconda mappa, questo potrebbe non essere il comportamento che vuoi.

+0

In effetti questo è esattamente il modo in cui ho implementato questo: – Massif

9

Un modo alternativo è questo:

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 

Consente di decidere il valore desiderato se sono presenti chiavi duplicate.

Esempio:

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

Si noti che la chiave 3 è diverso.

+0

Nota: non è effettivamente necessario specificare i tipi sui parametri di input. – Benjol

Problemi correlati