2012-04-01 13 views
5

ho List[(String,String)] e ho bisogno di ordinare loro dal secondo valore e tornare una mappaOrdina mappa per valore

ho fatto quanto segue:

val newMap = list.sortBy(_._2).foldLeft(Map.empty[String, String]) { 
     (map, key) ⇒ map + (key._1 → key._2) 
    } 

lista è un List[(String,String)]

Tuttavia la mappa di ritorno non è ordinata !!

+3

Penso che dovresti dichiarare il motivo per cui devi restituire una 'Mappa 'e che senso ha che ti interessa. Per esempio; successivamente desideri aggiungere coppie di valori-chiave in più? –

risposta

9

Le implementazioni di default Map sono basate su hash e non conservano l'ordine. Invece usano scala.collection.mutable.LinkedHashMap:

val newMap = list.sortBy(_._2).foldLeft(new LinkedHashMap[String, String]) { 
    (map, key) => map += (key._1 -> key._2) 
    map 
} 

Come suggerito da @Rex Kerr, scala.collection.immutable.ListMap potrebbe essere una scelta migliore per tipo di target:

val newMap = list.sortBy(_._2).foldLeft(new ListMap[String, String]) { 
    (map, key) => map + (key._1 -> key._2) 
} 

Or (ancora una volta pieni crediti dovrebbero andare a @Rex Kerr):

val newMap = new ListMap() ++ list.sortBy(_._2) 

Tuttavia che cosa si vuole veramente raggiungere? Sembra che si potrebbe essere scegliendo struttura di dati sbagliato ...

+0

Non sono d'accordo con questa risposta perché è fuorviante: stai restituendo una struttura mutabile che ** non è stata ordinata in tutti **. È semplicemente * traversabile nell'ordine di inserzione * –

+2

@oxbow_lakes: Penso che questo sia esattamente ciò che OP chiede (basato sul codice di esempio) - ha una 'Mappa' da' chiave' -> 'valore' ma con voci ordinate per' valore' . Tuttavia, l'OP deve decidere quale risposta è corretta o chiarire. A proposito, non ho downvoted la tua risposta in cambio, per essere chiari ;-). –

+0

Le voci non sono "ordinate" - sono attraversabili in un ordine prevedibile. Questa non è la stessa cosa –

2

mia ipotesi dalla tua domanda (che è evidente non al 100%): si desidera avere un Map[A, B] che viene ordinato in base al B

Questo è non possibile; la scala mappa ordinata è SortedMap[A, B] e questa deve essere ordinata secondo alcuni ordini sul tipo A.

Se quello che cercate è una sequenza di coppie percorribile (A, B) secondo B, allora hai bisogno di un Map e la soluzione:

list sortBy (_._2) 

... sarà sufficiente. Se si desidera avere una Map, la risposta di Tomasz sembra allettante, ma è fuorviante. La mappa è non ordinata; è attraversabile in un ordine noto (l'ordine di inserimento). Questo è non la stessa cosa - le aggiunte successive alla Mappa appariranno alla fine (da una prospettiva trasversale) indipendentemente da quale sia il valore. Quindi penso che sia necessario porsi una domanda: cosa sto cercando di fare?

Se ti interessa attraversare una sequenza di coppie in base ai secondi elementi, non hai bisogno di una mappa.

+0

Ho chiarito che cosa stavo assumendo che l'OP sta cercando di fare (cioè creare una 'SortedMap [A, B]' che è ordinata in base a 'B') e quindi spiegare perché questo è impossibile –

1

Questo dovrebbe essere semplice come:

val input = List((1,1), (3,4), (20,19), (2,2)) 
val output = input.sortBy(_._2).toMap 

output è:

Mappa (1-> 1, 2-> 2, 3-> 4, 20-> 19)