Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mutating a mutable collection using map?

Tags:

scala

If you have a mutable data structure like an Array, is it possible to use map operations or something similar to change its values?

Say I have val a = Array(5, 1, 3), what the best way of say, subtracting 1 from each value? The best I've come up with is

for(i <- 0 until a.size) { a(i) = a(i) - 1 }

I suppose way would be make the array a var rather than a val so I can say

a = a map (_-1)

edit: fairly easy to roll my own if there's nothing built-in, although I don't know how to generalise to other mutable collections

scala> implicit def ArrayToMutator[T](a: Array[T]) = new {
     |   def mutate(f: T => T) = a.indices.foreach {i => a(i) = f(a(i))}
     | }
ArrayToMutator: [T](a: Array[T])java.lang.Object{def mutate(f: (T) => T): Unit}

scala> val a = Array(5, 1, 3)
a: Array[Int] = Array(5, 1, 3)

scala> a mutate (_-1)

scala> a
res16: Array[Int] = Array(4, 0, 2)
like image 421
Luigi Plinge Avatar asked Aug 25 '11 03:08

Luigi Plinge


2 Answers

If you don't care about indices, you want the transform method.

scala> val a = Array(1,2,3)
a: Array[Int] = Array(1, 2, 3)

scala> a.transform(_+1)
res1: scala.collection.mutable.WrappedArray[Int] = WrappedArray(2, 3, 4)

scala> a
res2: Array[Int] = Array(2, 3, 4)

(It returns a copy of the wrapped array so that chaining transforms is more efficient, but the original array is modified as you can see.)

like image 179
Rex Kerr Avatar answered Oct 19 '22 17:10

Rex Kerr


How about using foreach since you don't really want to return a modified collection, you want to perform a task for each element. For example:

a.indices.foreach{i => a(i) = a(i) - 1}

or

a.zipWithIndex.foreach{case (x,i) => a(i) = x - 1}
like image 4
dhg Avatar answered Oct 19 '22 17:10

dhg