2017-06-05 1 views
0

Salut J'ai les données suivantes et je veux le mapper au premier élément du second paramètre. Donc, pour:Comprendre l'objet Scala Map lors du mappage vers la tête d'une liste

1 -> List((1,11)) 
1 -> List((1,1), (1,111)) 

Je veux:

(1,11) 
(1,1) 

Lorsque ces données sont dans un RDD je peux faire ce qui suit:

scala> val m = sc.parallelize(Seq(11 -> List((1,11)), 1 -> List((1,1),(1,111)))) 
m: org.apache.spark.rdd.RDD[(Int, List[(Int, Int)])] = ParallelCollectionRDD[198] at parallelize at <console>:47 

scala> m.map(_._2.head).collect.foreach(println) 
(1,11) 
(1,1) 

Cependant, quand il est dans un objet de la carte (résultat d'un groupePar) Je reçois ce qui suit:

scala> val m = Map(11 -> List((1,11)), 1 -> List((1,1))) 
m: scala.collection.immutable.Map[Int,List[(Int, Int)]] = Map(11 -> List((1,11)), 1 -> List((1,1), (1,111))) 

scala> m.map(_._2.head) 
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1) 

Quand je associez à toute la liste-je obtenir ce que j'attendais, mais pas quand je l'appelle tête il

scala> m.map(_._2) 
res2: scala.collection.immutable.Iterable[List[(Int, Int)]] = List(List((1,11)), List((1,1), (1,111))) 

Je peux aussi obtenir le résultat que je veux si je fais une des opérations suivantes:

scala> m.map(_._2).map(_.head) 
res4: scala.collection.immutable.Iterable[(Int, Int)] = List((1,11), (1,1)) 

scala> m.values.map(_.head) 
res5: Iterable[(Int, Int)] = List((1,11), (1,1)) 

Quelqu'un pourrait expliquer s'il vous plaît ce qui se passe ici?

+0

vous pouvez également faire 'm.toSeq.map (_._ 2.head)' pour obtenir le résultat désiré – perreal

Répondre

4

Ceci est un peu délicat et dépend du paramètre implicite CanBuildFrom de la carte. Selon le type de sortie de votre fonction, il sera capable de construire une structure ou l'autre (elle sera construite par le CanBuildFrom implicite).

m.map(_._2.head) // The passed function retrieves a pair (Int, Int) 

Il y a un CanBuildFrom implicite de (A, A) Carte [A, A], cet objet est passé à votre carte implicitement, c'est pourquoi, dans ce cas, le l'objet retourné est la carte [Int, Int ]

sur l'autre cas, vous avez

m.map(_._2) // The passed function retrieves a List[(Int, Int)] 

le CanBuildFrom implicite Liste [a] va construire un Iterable [a], dans ce cas de la liste [(Int, Int)] pour Iterable [(Int, Int)]

2

La ma L'opération p sur un scala.collection.immutable.Map se comporte différemment en fonction du type de retour de l'opération de carte.

Lorsque le type de retour si de type Tuple2 [T, P]:

la sortie des résultats d'opération de la carte dans un autre Map avec le premier élément du tuple _1 que la clé et le second élément _2 comme valeur.

par exemple

scala> m.map(_ => 10 -> 1) 
res14: scala.collection.immutable.Map[Int,Int] = Map(10 -> 1) // note the return type is Map. 

Lorsque le type de retour est autre chose que Tuple2:

lorsque le type de retour est autre chose que Tuple2 puis sortie de l'opération de la carte est une liste.

scala> m.map(_ => 10) 
res15: scala.collection.immutable.Iterable[Int] = List(10, 10) // note that the return type now is a List. 

donc avec le fait ci-dessus mis en place, pour une valeur de MapMap(11 -> List((1,11)), 1 -> List((1,1))) l'opération m.map(_._2.head) produit des valeurs Tuple2 (1, 11) et (1,1). puisque la première valeur (_1) de chaque article Tuple2 est 1 (c'est-à-dire que la clé de chaque valeur est 1), le (1,1) écrase (1,11) et nous nous retrouvons avec une valeur unique de (1,1).

Dans d'autres cas, l'opération de carte ne renvoie pas les types de Tuple2 et par conséquent, il en résulte List type au lieu de Map types d'où la différence est le résultat.