Scala: apply Map to a list of tuples

拥有回忆 提交于 2019-12-31 07:31:13

问题


very simple question: I want to do something like this:

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}})

I tried a lot differnt syntax versions, but I failed with all of them. How could I solve this? It can not be very difficult ...

Thanks!


回答1:


Multiple approaches to solve this, consider for instance the use of collect which delivers an immutable collection arr4, as follows,

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

With a for comprehension like this,

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



回答2:


I think you want to do something like

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)



回答3:


I think there are two problems:

  1. You're using foreach, which returns Unit, where you want to use map, which returns an Array[B].

  2. You're trying to update an immutable value, when you want to return a new, updated value. This is the difference between _._2 = _._2 * factor and _._2 * factor.

To filter the values not meeting the threshold:

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

To keep all values, but only multiply the ones meeting the threshold:

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



回答4:


You can do it with this,

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



回答5:


How about this?

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 is generally functional, which means you do not change values, but create new values, for example you do not write x._2 = …, since tuple is immutable (you can't change it), but create a new tuple.




回答6:


This will do what you need.

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

The key here is that you can return tuple from the map lambda expression by putting two variable into (..).

Edit: You want to change every element of an array without creating a new array. Then you need to do the next.

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


来源:https://stackoverflow.com/questions/27570235/scala-apply-map-to-a-list-of-tuples

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!