在数组上执行循环操作的功能方法

Functional way of doing a loop of operations on an array

我目前有一个 Java 程序,它执行如下操作:

  int nvars = 10;
  long vars[] = new long[nvars];
  for(int i = 0; i < nvars; i++) {
      vars[i] = someFunction(i);
      anotherFunction(vars[i]);
  }

我正在将它转换为 Scala 代码并具有:

val nvars: Int = 10
val vars: Array[Long] = new Array[Long](nvars)

for ( i <- 0 to nvars-1 )
    vars(i) = someFunction(i)
    anotherFunction(vars(i))
}

关于如何使这个(更多)功能有任何建议吗?

Array伴生对象中有很多有用的构造方法,比如你这里的情况,可以使用tabulate:

val nvars: Int = 10
val vars = Array.tabulate(nvars){ someFunction } // calls someFunction on the values 0 to nvars-1, and uses this to construct the array
vars foreach (anotherFunction) // calls anotherFunction on each entry in the array

如果 anotherFunction returns 是一个结果而不仅仅是一个 "side-effect" 函数,您可以通过调用 map:

来捕获它
val vars2 = vars map (anotherFunction) // vars2 is a new array with the results computed from applying anotherFunction to each element of vars, which is left unchanged.

考虑迭代 Long 个值的范围,

val vars = (1L to 10L).map(someFunction).map(anotherFunction)

这会将 someFunction 应用于范围中的每个值,然后将第一个 map 的每个中间结果应用于 anotherFunction。假设每个函数接受并传递类型为 Long.

的值

要将 vars 转换为所需的集合,例如 ArrayList,请考虑,

vars.toArray
vars.toList

使用 view 将两个函数同时应用于范围内的每个值,因此不必从映射 someFunction

创建中间集合
(1L to 10L).view.map(someFunction).map(anotherFunction)

使用map。在 Array 上调用映射将 return 一个新集合。因此,为每个要应用于 Array.

的所有元素的函数调用 map 两次

一些简单的功能演示:

scala> def addOne(l: Long) = l + 1
addOne: (l: Long)Long

scala> def addTwo(l: Long) = l + 2
addTwo: (l: Long)L

map 数组 vars 使用定义的函数。

scala> val vars = Array[Long](1,2,3,4,5,6,7,8,9,10)
vars: Array[Long] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> vars.map(addOne(_))
res0: Array[Long] = Array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)

scala> vars.map(addOne(_)).map(addTwo(_))
res1: Array[Long] = Array(4, 5, 6, 7, 8, 9, 10, 11, 12, 13)

另一种 "more functional" 方法可能是一个很好的练习,它是使用递归函数,该函数将函数作为参数并将传入的函数应用于 List 的每个元素。

scala> def fun[A](as: List[A], f: A => A): List[A] = as match {
     | case List() => List()
     | case h::t => f(h) :: fun(t, f)
     | }
fun: [A](as: List[A], f: A => A)List[A]