2011-01-25 5 views
23

Jak sortować mapę tego rodzaju:Scala mapa sortowania

"01" -> List(34,12,14,23), "11" -> List(22,11,34) 

wartościami początku?

+0

Czy potrzebujesz wyniku, aby być kolejną mapą, czy po prostu chcesz zapomnieć o klawiszach, gdy zostały użyte do sortowania? –

+0

Potrzebuję wyniku na innej mapie. –

+5

Myślę, że mapy są z definicji nieposortowane, prawda? – coubeatczech

Odpowiedz

57

Jednym ze sposobów jest użycie scala.collection.immutable.TreeMap, który jest zawsze posortowany według klawiszy:

val t = TreeMap("01" -> List(34,12,14,23), "11" -> List(22,11,34)) 

//If you have already a map... 
val m = Map("01" -> List(34,12,14,23), "11" -> List(22,11,34)) 
//... use this 
val t = TreeMap(m.toSeq:_*) 

można przekonwertować go do seq lub Lista i sortować je, zbyt:

//by specifying an element for sorting 
m.toSeq.sortBy(_._1) //sort by comparing keys 
m.toSeq.sortBy(_._2) //sort by comparing values 

//by providing a sort function 
m.toSeq.sortWith(_._1 < _._1) //sort by comparing keys 

Istnieje wiele możliwości, z których każda jest mniej lub bardziej wygodna w określonym kontekście.

+0

Możesz również dołączyć dowolnie posortowaną sekwencję do 'LinkedHashMap', która zachowa kolejność wstawiania dla przejścia. –

+0

heh heh, właśnie zaktualizowałem moją odpowiedź, aby użyć '.toseq: _ *', nie zauważyłem, że już to zrobiłeś! Obiecuję, że nie kradnę :) –

+0

TreeMap z toSeq był bardzo pomocny. –

15

Jak stwierdzono, domyślny typ Map jest nieposortowane, ale zawsze SortedMap

import collection.immutable.SortedMap 
SortedMap("01" -> List(34,12,14,23), "11" -> List(22,11,34)) 

Chociaż Zgaduję, nie można używać, bo uznaję tę pracę domową i podejrzewasz, że mapa jest wynikiem operacji groupBy. Więc trzeba utworzyć pusty SortedMap i dodać wartości:

val unsorted = Map("01" -> List(34,12,14,23), "11" -> List(22,11,34)) 
val sorted = SortedMap.empty[String, List[Int]] ++ unsorted 
//or 
val sorted = SortedMap(unsorted.toSeq:_*) 

Albo jeśli nie jesteś przywiązane do interfejsu Map, można po prostu przekonwertować go na sekwencję krotek. Należy zauważyć, że to podejście będzie działać tylko wtedy, gdy zarówno klucze, jak i wartości mają zdefiniowaną kolejność. Listy nie mają zdefiniowanej kolejności domyślnej, więc nie będzie to działać z twoim przykładowym kodem - dlatego zamiast tego wymyśliłem kilka innych liczb.

val unsorted = Map("01" -> 56, "11" -> 34) 
val sorted = unsorted.toSeq.sorted 

Może to być przydatne, jeśli można najpierw przekonwertować list do jakiegoś innego typu (takiego jak łańcuch), która jest najlepiej wykonać przy użyciu mapValues

aktualizacji: Odpowiedź Zobacz Landei, która pokazuje, jak możesz podać niestandardową funkcję sortowania, dzięki której to podejście będzie działać.