【问题标题】:Scala MapReduce FilterScala MapReduce 过滤器
【发布时间】:2018-03-08 21:19:44
【问题描述】:

有没有办法在 Scala 中执行以下操作?

假设我有一个大小为 15 的 Double 数组:

[10,20,30,40,50,60,70,80,Double.NaN,Double.NaN,110,120,130,140,150]

我想使用 map reduce 将所有 Double.NaN(从左到右)替换为数组中最后四个值的平均值。所以第一个 Double.NaN 被 60 替换,下一个 Double.NaN 被替换为 64(即,之前计算的索引 8 处的 60 用于此计算)。

到目前为止,我已经使用函数类型参数来获取Double.NaN 的位置。

【问题讨论】:

  • 您是在寻找简单的 scala 解决方案还是在使用 MapReduce(hadoop/bigdata 处理框架)?

标签: scala functional-programming mapreduce


【解决方案1】:

在这种情况下,我不确定您所说的“map-reduce”到底是什么意思。它看起来很像 scanLeft 的用例:

import scala.collection.immutable.Queue
val input = List[Double](
  10,20,30,40,50,60,70,80,Double.NaN,
  Double.NaN,110,120,130,140,150
)
val patched = input.
  scanLeft((Queue.fill(5)(0d), 0d)){ 
    case ((q, _), x) => { 
      val y = if (x.isNaN) q.sum / 5 else x; 
      (q.dequeue._2.enqueue(y), y)
    }
  }.unzip._2.tail

创建结果:

List(10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 60.0, 64.0, 110.0, 120.0, 130.0, 140.0, 150.0)

一般来说,除非间隙“很少”,否则这不适用于典型的 map-reduce 工作流程,因为

  • 结果列表中的每个值都可以依赖于其左侧的任意多个值,因此您不能将数据集分割成独立的块并map 它们独立地进行。
  • 你没有减少任何东西,你想要一个修补过的列表

如果你不映射也不减少,我不会称之为“map-reduce”。

顺便说一句:上面的代码适用于“5”的任何(正整数)值。

【讨论】:

    【解决方案2】:

    请注意,对给定示例 (50,60,70,80) 中第一个 NaN 的最后四个值求平均得到 65,而不是 60。最后五个将得到 60。

    它必须是 map-reduce 吗?折叠怎么样?

    (List[Double]() /: listOfDoubles)((acc: List[Double], double: Double) => {(if (double.isNaN)
      acc match {
        case Nil => 0.0 // first double in the list
        case _ => {
          val last5 = acc.take(5)
          (0.0 /: last5)(_ + _) / last5.size // in case there's only a last 1, 2, 3, or 4 instead of 5
          }
        }
    else double) :: acc}).reverse
    

    【讨论】:

      猜你喜欢
      • 2013-05-01
      • 1970-01-01
      • 2015-12-28
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多