2015-06-11 2 views
0

я в настоящее время есть программа 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)) 
} 

Любые советы о том, как сделать это (более) функциональным?

+1

В математическом смысле, функции не имеют побочных эффектов, так что вы можете сделать свой «многочисленные функции» побочный эффект свободный, возвращая новый массив (или неизменный список) –

ответ

7

Есть много полезных методов конструктора в объекте массива компаньона, например, для вашей ситуации здесь, вы можете использовать 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 Если возвращает результат, а не просто быть «бок- функция эффекта», вы можете вместо этого захватить это с вызовом 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. 
+0

Престижность @Shadowlands! – Daniel

+0

Вопрос: не то, что вы предлагаете, эквивалентно двум последовательным циклам? Я имею в виду, с точки зрения вычислительной эффективности, насколько это оптимально? – Daniel

+0

@ Daniel. Что касается сложности, 2 петли так же сложны, как 1, либо как 10. Они все еще линейны (O (n)). – dcastro

1

Рассматривает итерацию диапазоне Long значений,

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

Это относится someFunction на каждое значение из диапазона, а затем каждый промежуточный результат с первого map на anotherFunction. Предполагается, что каждая функция принимает и передает значения типа Long.

Для преобразования vars на нужную коллекцию, такие как Array или List считают,

vars.toArray 
vars.toList 

Используйте view, чтобы применить оба функции сразу на каждое значение в диапазоне, следовательно, не имея, чтобы создать промежуточную коллекцию из отображения someFunction,

(1L to 10L).view.map(someFunction).map(anotherFunction) 
4

Использование map. Призыв к карте на Array вернет новую коллекцию. Поэтому вызовите map дважды для каждой функции, которую вы хотите применить ко всем элементам Array.

Некоторые простые функции для демонстрации:

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) 

Другой подход, который является «более функциональным» и, вероятно, является хорошим упражнением является использование рекурсивной функции, которая принимает функцию в качестве параметра и применяется функция, которая передается каждому элементу 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] 
Смежные вопросы