9

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)
Luigi Plinge
  • 50,650
  • 20
  • 113
  • 180

2 Answers2

18

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

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • Cool, I thought there must be something. Any ideas on comparative efficiency between this, pimping the library as in the question, or using a normal function? – Luigi Plinge Aug 25 '11 at 05:37
  • 1
    @Luigi Plinge - If you specialize your version and are using primitive types, yours will be faster (unless you hit a specialization bug, of which there are a few). Otherwise the library is just as fast as you. – Rex Kerr Aug 25 '11 at 05:53
4

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}
dhg
  • 52,383
  • 8
  • 123
  • 144