【问题标题】:Spark Mapvalues vs. MapSpark Mapvalues 与 Map
【发布时间】:2016-05-11 05:28:47
【问题描述】:

所以我在 stackoverflow 上看到另一个用户提出的这个问题,我在尝试练习 scala 和 spark 时尝试自己编写代码:

问题是从列表中找到每个键的平均值:

假设列表为:( (1,1), (1,3), (2,4), (2,3), (3,1) )

代码是:

val result = input.combineByKey(
(v) => (v, 1),
(acc: (Int, Int), v) => (acc._1 + v, acc._2 + 1),
(acc1: (Int, Int), acc2: (Int, Int)) => (acc1._1 + acc2._1, acc1._2 + acc2._2)).
map{ case (key, value) => (key, value._1 / value._2.toFloat) }  
result.collectAsMap().map(println(_))

所以基本上上面的代码将创建一个[Int, (Int, Int)]类型的RDD,其中第一个Int是键,值是(Int, Int),第一个Int是所有具有相同值的值的相加键,第二个Int 是键出现的次数。

我明白发生了什么,但出于某种原因,当我这样重写代码时:

val result = input.combineByKey(
(v) => (v, 1),
(acc: (Int, Int), v) => (acc._1 + v, acc._2 + 1),
(acc1: (Int, Int), acc2: (Int, Int)) => (acc1._1 + acc2._1, acc1._2 + acc2._2)).
mapValues(value: (Int, Int) => (value._1 / value._2))
result.collectAsMap().map(println(_))

当我使用 mapValues 而不是带有 case 关键字的 map 时,代码不起作用。它会给出错误提示 error: not found: type / 使用带有 case 和 mapValues 的 map 有什么区别。因为我认为映射值只会取值(在这种情况下是 (Int,Int))并返回给您一个新值,并且键值对的键保持不变。

【问题讨论】:

标签: scala apache-spark


【解决方案1】:

试试

val result = input.combineByKey(
(v) => (v, 1),
(acc: (Int, Int), v) => (acc._1 + v, acc._2 + 1),
(acc1: (Int, Int), acc2: (Int, Int)) => (acc1._1 + acc2._1, acc1._2 + acc2._2)).
mapValues(value => (value._1 / value._2))
result.collectAsMap().map(println(_))

【讨论】:

  • 哦,这也行得通!为什么你不需要value: (Int, Int)?我也这样做了,它奏效了:result.map(elem => (elem._1, (elem._2._1 / elem._2._2))).collectAsMap().map(println(_))
  • @1290 我不知道确切的答案,但您不需要在 spark 转换/操作中明确指定 rdd 的数据类型。
  • 哦,好的,我明白了。谢谢!
【解决方案2】:

没关系,我找到了一篇很好的文章来解决我的问题:http://danielwestheide.com/blog/2012/12/12/the-neophytes-guide-to-scala-part-4-pattern-matching-anonymous-functions.html

如果其他人有同样的问题,解释得很好!

【讨论】:

    猜你喜欢
    • 2016-08-10
    • 1970-01-01
    • 2014-10-27
    • 2018-06-10
    • 2015-03-16
    • 1970-01-01
    • 2021-04-04
    • 2021-05-21
    • 1970-01-01
    相关资源
    最近更新 更多