【问题标题】:Scala Convert For Loop to Functional MethodScala 将 For 循环转换为函数式方法
【发布时间】:2015-06-16 13:13:07
【问题描述】:

我想将以下 for 循环转换为函数式 Scala 方法。

for (i <- 15 to 25){
  count_table_rdd = count_table_rdd.union(training_data.map(line => (i+"_"+line(i)+"_"+line(0), 1)).reduceByKey(_ + _))
}

我已经尝试查看 foreach 方法,但我不想转换每个项目,只是从 15 到 25。

【问题讨论】:

  • Scala 集合上有一个slice(from:Int, to:Int) 方法,所以如果你可以切片然后foreach 你就可以设置好了
  • 您在实际用例中真的需要i 的值吗?或者只是line(i)

标签: scala for-loop functional-programming apache-spark


【解决方案1】:

你可以折叠。

val result = (count_table_rdd /: (15 to 25)){ (c, i) => c.union(...) }

如果你看到你有一组数据并且你正在通过它推送一个值来更新那个值,你应该去折叠,因为这正是它所做的。

【讨论】:

  • 我以为多米诺骨牌运算符现在不受欢迎?
  • @JustinPihony - 嗯,Martin Odersky 做了一个很好的案例,它非常准确地在视觉上代表了正在发生的事情。 foldLeft 让你在初始列表/参数和闭包之间切换你头脑中的参数顺序。
【解决方案2】:

您也可以使用tailrec,但您应该遵循@rex 的方法。 它不会编译,相应地指定your count_table_rddres的类型

tailrec 版本:

@annotation.tailrec
  def f(start: Int = 15, end: Int = 25,res:List[Your_count_table_rdd_Type]=Nil): List[Your_count_table_rdd_Type] = {
    if (start > end) count_table_rdd
    else {
     val temp = res ++ training_data.map(line => (start + "_" + line(start) + "_" + line(0), 1)).reduceByKey(_ + _)
      f(start + 1, end,temp)
    }
  }

  f()

你也可以指定开始和结束。

f(30,45)

【讨论】:

  • 这不起作用;你正在变异count_table_rdd。再试一次?
  • @RexKerr 我已经编辑了我的答案,感谢您指出:),现在正确吗?
【解决方案3】:

从 Spark 的角度来看,最好通过转换 trainingDataRDD 而不是循环选择给定列来做到这一点。

类似:

trainingData.flatMap(line => (15 to 25).map(i => (i+"_"+line(i)+"_"+line(0), 1)))
        .reduceByKey(_ + _)

这将比使用union 将RDD 的各个部分连接在一起更有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 1970-01-01
    • 2017-10-26
    • 1970-01-01
    相关资源
    最近更新 更多