J'ai un Seq
contenant des objets d'une classe qui ressemble à ceci:
class A (val key: Int, ...)
Maintenant, je veux convertir ce Seq
en Map
, en utilisant la valeur key
de chaque objet comme clé et l'objet lui-même comme valeur. Alors:
val seq: Seq[A] = ...
val map: Map[Int, A] = ... // How to convert seq to map?
Comment puis-je le faire de manière efficace et élégante dans Scala 2.8?
Mappez sur votre Seq
et produisez une séquence de tuples. Utilisez ensuite ces tuples pour créer un Map
. Fonctionne dans toutes les versions de Scala.
val map = Map(seq map { a => a.key -> a }: _*)
Depuis 2.8 Scala a eu .toMap
, alors:
val map = seq.map(a => a.key -> a).toMap
ou si vous voulez éviter de construire une séquence intermédiaire de tuples:
val map: Map[Int, A] = seq.map(a => a.key -> a)(collection.breakOut)
Une autre variante de 2,8, pour faire bonne mesure, également efficace:
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)))
Notez que si vous avez des clés en double, vous en supprimerez certaines lors de la création de la carte! Vous pouvez utiliser groupBy
pour créer une carte où chaque valeur est une séquence:
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))))
Comme scala sait convertir un Tuple de deux en une carte, vous voudriez d'abord convertir votre seq en Tuple et ensuite la mapper ainsi (peu importe si c'est int, dans notre cas chaîne, chaîne):
L'algorithme général est le suivant:
Ou pour résumer:
Étape 1: Seq -> Tuple de deux
Étape 2: Tuple de deux -> Carte
Exemple:
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)