2017-06-05 164 views
0

嗨,我有以下數據並希望將它映射到第二個參數中的第一項。因此,對於:在映射到列表頭時瞭解Scala映射對象

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

我想:

(1,11) 
(1,1) 

當該數據是在RDD我可以做到以下幾點:

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) 

然而,當它是一個Map對象(一個GROUPBY的結果)我得到以下幾點:

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) 

當我映射到整個列表我得到了我所期望的,但不是當我打電話頭就可以了

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

我也能得到我想要的結果,如果我做了以下之一:

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)) 

請問有人可以解釋一下這裏發生了什麼?

+0

你也可以通過'm.toSeq.map(_._ 2.head)'得到想要的結果 – perreal

回答

4

這有點棘手,取決於地圖的隱式參數CanBuildFrom。根據函數f的輸出類型,它將能夠構建一個結構或另一個結構(它將由隱式CanBuildFrom構建)。

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

,由(A,A),以圖[A,A],該對象被傳遞到地圖隱含一個隱含CanBuildFrom,這就是爲什麼在這種情況下,返回的對象是地圖[INT,INT ]

在其他情況下,你有

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

的列表[A]將建立一個可迭代[A],在這種情況下,從列表[(INT,INT)],以可迭代[(隱式CanBuildFrom Int,Int)]

2

The ma scala.collection.immutable.Map上的p操作的行爲取決於映射操作的返回類型。

當如果類型Tuple2 [T,P]的返回類型:

在另一個Map地圖運算結果的輸出與該元組_1作爲密鑰和所述第二元件的第一元件_2作爲值。

例如

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

當返回類型是什麼比Tuple2其他:

當返回類型比Tuple2任何其他那麼,地圖操作的輸出是一個列表。

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

所以與上述既定的事實,爲的值Map(11 -> List((1,11)), 1 -> List((1,1)))操作m.map(_._2.head)一個Map產生Tuple2值(1, 11)(1,1)。由於每個元組2的項目的第一個值(_1)是1(即,每個值的密鑰是1),所以(1,1)覆蓋(1,11)並且我們以單個值(1,1)結束。

在其他情況下在地圖操作犯規返回類型Tuple2的,因此它導致List型代替Map類型的,因此不同的是結果。