Scala对:如何计算值中出现的次数(数字列表)

时间:2019-03-09 17:32:21

标签: scala apache-spark

我有一个RDD [(Int,ListBuffer [Byte])],我喜欢对列表中的每个数字执行“字数统计”。 例如,RDD为:

(31000,ListBuffer(1, 1, 0, 1, 0, 1, 1, 1, 1))
(21010,ListBuffer(0, 0, 0))
(23000,ListBuffer(1, 1, 1, 1, 1))
(01000,ListBuffer(1, 1))
(34000,ListBuffer(0))

我想得到这个:

(31000,(0,2),(1,7)) // this could be a Map[0=>2, 1=>7]
(21010,(0,3))
(23000,(1,5))
(01000,(1,2))
(34000,(0,3))

有指导吗?预先谢谢你

编辑:有人建议重复我的问题,但建议的帖子仅涉及一个列表,但我想申请一个结对(整数,列表)。

1 个答案:

答案 0 :(得分:5)

获取Scala集合中的值的直方图的最惯用的方法是使用groupBy,然后使用一个映射图,该映射图将得出每个结果组的大小:

scala> import collection.mutable.ListBuffer
import collection.mutable.ListBuffer

scala> val values = ListBuffer(1, 1, 0, 1, 0, 1, 1, 1, 1)
values: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 1, 0, 1, 0, 1, 1, 1, 1)

scala> values.groupBy(identity).mapValues(_.size)
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 7, 0 -> 2)

在这种情况下,该部分与Spark部分完全独立-您恰好对RDD中的值执行此操作,但是完整的解决方案如下所示:

scala> val counts = myRdd.mapValues(_.groupBy(identity).mapValues(_.size))
counts: org.apache.spark.rdd.RDD[(Int, scala.collection.immutable.Map[Int,Int])] = MapPartitionsRDD[1] at mapValues at <console>:26

scala> counts.foreach(println)
(1000,Map(1 -> 2))
(21010,Map(0 -> 3))
(23000,Map(1 -> 5))
(34000,Map(0 -> 1))
(31000,Map(1 -> 7, 0 -> 2))

值得注意的是,Scala集合上的mapValues是惰性的,这意味着每次在RDD中使用映射时,都会重新计算值。可能不错,但是如果您担心的话,可以将其替换为以下内容:

values.groupBy(identity).map { case (k, v) => k -> v.size }

...这将返回经过严格评估的地图。