【问题标题】:How to specify a 'next' function in Scala for loop如何在 Scala for 循环中指定“下一个”函数
【发布时间】:2017-03-12 15:42:27
【问题描述】:

我有一个这样的代码 sn-p:

val step = Step.Montyly  //this could be Yearly, daily, hourly, etc.
val (lower, upper) = (****, ****) //unix timestamps, which represent a time range 
val timeArray = Array[Long](0)

var time = lower
while (time <= upper) {
    timeArray +: = time
    time = step.next(time) // eg, Step.Hourly.next(time) = time + 3600, Step.Monthly.next(time) = new DateTime(time).addMonths(1).toTimeStamp()
}

return timeArray

虽然这是用 Scala 编写的,但它是一种非功能性方式。我是 Scala 的新手,想知道这是否可以以功能方式重写。我知道以下内容:

for(i <- 1 to 10 by step) yield i

但是这里的step是一个固定值,如何让'i'可以由'next function'生成而不是固定值?

【问题讨论】:

    标签: scala loops for-loop functional-programming yield


    【解决方案1】:

    您必须稍微更改流程以使其正常运行(没有可变的Array 和没有var)。 Stream.iterate 使用初始起始值,并重复应用函数以生成下一个元素。

    Stream.iterate(lower)(step.next).takeWhile(_ < upper)
    

    【讨论】:

    • 我喜欢这个!此外,如果您想要一个经过严格评估的解决方案,List 也提供相同的功能。
    • @Reactormonk,谢谢!我现在可以清除项目中的非功能代码。我喜欢这种优雅而富有表现力的方式:)
    • @stefanobaghino 是的,但它不会终止。
    【解决方案2】:

    Reactormonk 的答案可能是我在实践中会使用的答案,但这里有一个替代的全功能尾递归答案(采用任何你喜欢的 step 函数)

      def next(n: Long) = n + 3 // simple example for illustration
    
      def steps(current: Long, upper: Long, f: Long => Long, result: List[Long]): Array[Long] =
      {
        if (current >= upper)
          result.reverse.toArray
        else 
          steps(f(current), upper, f, current :: result)
      } 
      steps(1, 20, next, List(0))
      //> res0: Array[Long] = Array(0, 1, 4, 7, 10, 13, 16, 19)
    

    【讨论】:

      猜你喜欢
      • 2022-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      相关资源
      最近更新 更多