Jak przekonwertować Seq[A] na mapę [Int, A] używając wartości A jako klucza na mapie?

Mam Seq zawierające obiekty klasy, które wyglądają tak:

class A (val key: Int, ...)

Teraz chcę przekonwertować to {[2] } na Map, używając key wartości każdego obiektu jako klucza, a samego obiektu jako wartości. Więc:

val seq: Seq[A] = ...
val map: Map[Int, A] = ... // How to convert seq to map?

Jak mogę to zrobić sprawnie i elegancko w Scali 2.8?

Author: Eugene Yokota, 2010-05-28

4 answers

Odwzoruj Seq i wytworz sekwencję krotek. Następnie użyj tych krotek, aby utworzyć Map. Działa we wszystkich wersjach Scali.

val map = Map(seq map { a => a.key -> a }: _*)
 27
Author: Daniel Spiewak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-27 22:08:38

Od 2.8 Scala mA .toMap, więc:

val map = seq.map(a => a.key -> a).toMap

Lub jeśli chcesz uniknąć konstruowania pośredniego ciągu krotek:

val map: Map[Int, A] = seq.map(a => a.key -> a)(collection.breakOut)

 50
Author: Seth Tisue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-22 18:52:17

Jeszcze jedna odmiana 2.8, na dobrą miarę, również skuteczna:

scala> case class A(key: Int, x: Int)
defined class A

scala> val l = List(A(1, 2), A(1, 3), A(2, 1))
l: List[A] = List(A(1,2), A(1,3), A(2,1))

scala> val m: Map[Int, A] = (l, l).zipped.map(_.key -> _)(collection.breakOut)
m: Map[Int,A] = Map((1,A(1,3)), (2,A(2,1)))

Zauważ, że jeśli masz zduplikowane klucze, niektóre z nich odrzucisz podczas tworzenia mapy! Możesz użyć groupBy, aby utworzyć mapę, gdzie każda wartość jest sekwencją:

scala> l.groupBy(_.key)
res1: scala.collection.Map[Int,List[A]] = Map((1,List(A(1,2), A(1,3))), (2,List(A(2,1))))
 6
Author: retronym,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-28 04:51:13

Ponieważ scala wie, aby przekonwertować krotkę dwóch na mapę, najpierw chcesz przekonwertować swój seq na krotkę, a następnie mapować tak (nie ma znaczenia, czy jest to int, w naszym przypadku string, string):

Ogólny algorytm jest następujący:

  1. dla każdej pozycji w Seq
  2. Item --> Tuple (klucz, wartość)
  3. dla każdej krotki (klucz, wartość)
  4. Agregat do Map (klucz, wartość)

Lub podsumowując:

Krok 1: Seq -- > krotka z dwóch

Krok 2: krotka z dwóch --> Mapa

Przykład:

case class MyData(key: String, value: String) // One item in seq to be converted to a map entry.

// Our sequence, simply a seq of MyData
val myDataSeq = Seq(MyData("key1", "value1"), MyData("key2", "value2"), MyData("key3", "value3")) // List((key1,value1), (key2,value2), (key3,value3))

// Step 1: Convert seq to tuple
val myDataSeqAsTuple = myDataSeq.map(myData => (myData.key, myData.value)) // List((key1,value1), (key2,value2), (key3,value3))

// Step 2: Convert tuple of two to map.
val myDataFromTupleToMap = myDataSeqAsTuple.toMap // Map(key1 -> value1, key2 -> value2, key3 -> value3)
 1
Author: Tomer Ben David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-10 09:40:39