我有一个RDD,其中的键是一个ID,值包括ID列表。我想按升序对值列表进行排序 例如
1, list(12,3,8,10)
2, list(42,3,65,33)
3, list(6,2,4,1)
输出
1, list(3,8,10,12)
2, list(3,33,42,65)
3, list(1,2,4,6)
RDD创建
因此,我在加入两个不同的RDD之后创建了RDD,然后使用它productIterator
创建了list of values
,这给了我RDD(Int, List[Any])
类型的RDD。
我尝试过
rdd.mapValues(x=> _.2.sorted)
不同的排序方法,但没有运气
答案 0 :(得分:2)
您快到了。
顾名思义, mapValues
仅将映射功能应用于值。您的代码看起来像您正在尝试从键/值元组中提取第二个元素,我想这会引发错误。
您可以使用map
或mapValues
。如果您希望保留密钥,map
需要返回一个元组,因此mapValues
比较简单,但是我将向您展示两种方式。因此,我们从已经构建的RDD[(Int, List[Int])]
开始,然后使用collect()
进行查看。
scala> start
res17: org.apache.spark.rdd.RDD[(Int, List[Int])] = MapPartitionsRDD[6] at map at <console>:37
scala> start.collect()
res18: Array[(Int, List[Int])] = Array((1,List(12, 3, 8, 10)), (2,List(42, 3, 65, 33)))
首先,让我们做最简单的事情:
scala> start.mapValues(x => x.sorted).collect()
res19: Array[(Int, List[Int])] = Array((1,List(3, 8, 10, 12)), (2,List(3, 33, 42, 65)))
如您所见,它将返回您期望的顺序。
使用地图修改键/值元组非常简单,只要您保留键即可。我建议使用Scala的case函数语法将元组分解为命名参数,而不必引用tuple._1
/ tuple._2
scala> start.map({ case (k, v) => (k, v.sorted) }).collect()
res21: Array[(Int, List[Int])] = Array((1,List(3, 8, 10, 12)), (2,List(3, 33, 42, 65)))
但是使用您熟悉的元组语法:
scala> start.map(x => (x._1, x._2.sorted)).collect()
res22: Array[(Int, List[Int])] = Array((1,List(3, 8, 10, 12)), (2,List(3, 33, 42, 65)))
我希望这会有所帮助。 编辑,因为您的问题似乎是由于缺少类型信息所致,所以我添加了如何创建用于场景运行的RDD。
val input: Array[Array[Int]] = Array(Array(1, 12, 3, 8, 10), Array(2, 42, 3, 65, 33))
val start: RDD[(Int, List(Int)] = sc.parallelize(input).map({
case Array(key, value @ _*) => (key, value.toList)
})
如果查看List.sorted的方法签名,则会看到它具有一个隐式参数,该参数告诉Scala如何对列表进行排序。
Scala为数字和字符串之类的东西提供默认实现,但是它根据List的类型查找隐式实现。它没有默认的Any
列表,这与Java中的Object
列表等效。因此,如果您可以修改问题以包含更多代码,则将有助于确定丢失该类型信息的位置。