2014-12-19 4 views
0

очень простой вопрос: Я хочу сделать что-то вроде этого:Scala: применять карты в список кортежей

var arr1: Array[Double] = ... 
var arr2: Array[Double] = ... 

var arr3: Array[(Double,Double)] = arr1.zip(arr2) 

arr3.foreach(x => {if (x._1 > treshold) {x._2 = x._2 * factor}}) 

Я пробовал много версий синтаксиса различно, но у меня не со всеми из них. Как я могу это решить? Это не может быть очень сложно ...

Спасибо!

+1

Было бы неплохо, если бы вы могли более подробную информацию, например, о некотором вводе и желаемом выходе. Тогда люди могут помочь вам, не догадываясь о вашем фактическом требовании. –

+0

Ваша проблема в том, что ваше мышление изменчиво, а не неизменно. Добро пожаловать в функциональный мир, на землю, где логика торжествует над ошибками. – samthebest

ответ

1

Я думаю, что вы хотите сделать что-то вроде

scala> val arr1 = Array(1.1, 1.2) 
arr1: Array[Double] = Array(1.1, 1.2) 

scala> val arr2 = Array(1.1, 1.2) 
arr2: Array[Double] = Array(1.1, 1.2) 

scala> val arr3 = arr1.zip(arr2) 
arr3: Array[(Double, Double)] = Array((1.1,1.1), (1.2,1.2)) 

scala> arr3.filter(_._1> 1.1).map(_._2*2) 
res0: Array[Double] = Array(2.4) 
0

Как об этом?

arr3.map { case(x1, x2) => // extract first and second value 
    if (x1 > treshold) (x1, x2 * factor) // if first value is greater than threshold, 'change' x2 
    else (x1, x2) // otherwise leave it as it is 
}.toMap 

Scala, как правило, функциональный, что означает, что вы не меняют значения, но и создают новые значения, например, вы не пишете x._2 = ..., так как кортеж неизменен (вы не можете изменить его), но создать новый кортеж.

0

Это сделает то, что вам нужно.

arr3.map(x => if(x._1 > treshold) (x._1, x._2 * factor) else x) 

Ключевым моментом здесь является то, что вы можете вернуть кортеж из лямбда-выражения карты, поставив две переменные в (..).

Редактировать: вы хотите изменить каждый элемент массива без создания нового массива. Тогда вам нужно сделать следующее.

arr3.indices.foreach(x => if(arr3(x)._1 > treshold) (arr3(x)._1, arr3(x)._2 * factor) else x) 
3

несколько подходов для решения этой проблемы, рассмотрим, например, использование collect которая обеспечивает неизменный сбор arr4, как следует,

val arr4 = arr3.collect { 
    case (x, y) if x > threshold => (x ,y * factor) 
    case v => v 
} 

С для понимания, как это,

for ((x, y) <- arr3) 
    yield (x, if (x > threshold) y * factor else y) 
1

Я думаю, что есть две проблемы:

  1. Вы используете foreach, который возвращает Unit, где вы хотите использовать map, который возвращает Array[B].

  2. Вы пытаетесь обновить неизменяемое значение, когда хотите вернуть новое обновленное значение. В этом разница между _._2 = _._2 * factor и _._2 * factor.

Чтобы отфильтровать значения не отвечающие порога:

arr1.zip(arr2).filter(_._1 > threshold).map(_._2 * factor) 

Чтобы сохранить все значения, но только умножать те встречи порог:

arr1.zip(arr2).map { 
    case (x, y) if x > threshold => y * factor 
    case (_, y)     => y 
} 
0

Вы можете сделать это с этим ,

arr3.map(x => if (x._1 > threshold) (x._1, x._2 * factor) else x)