如何在 Scala for 循环中指定 'next' 函数
How to specify a 'next' function in Scala for loop
我有这样的代码片段:
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'而不是一个固定值呢?
您必须稍微更改流程以使其正常运行(没有可变 Array
且没有 var
)。 Stream.iterate
使用初始起始值,并重复应用一个函数来生成下一个元素。
Stream.iterate(lower)(step.next).takeWhile(_ < upper)
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)
我有这样的代码片段:
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'而不是一个固定值呢?
您必须稍微更改流程以使其正常运行(没有可变 Array
且没有 var
)。 Stream.iterate
使用初始起始值,并重复应用一个函数来生成下一个元素。
Stream.iterate(lower)(step.next).takeWhile(_ < upper)
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)