1

I would like to transform an array of arrays. This can be done by:

var cal = Array.ofDim[Double](300, 10000);   
cal.foreach(x => x.transform(y => some_value))

The question is how to access the index of transformed cell. For example:

cal.foreach(x => x.transform(y => x(y.index - 1) + 7))

I tried to use zipWithIndex:

cal.foreach(x => x.zipWithIndex.transform(y => (x(y._2) + 7, y._2)));

but this didn't change the "cal" values.

Thanks.

3 Answers 3

4

The latter option doesn't work because you're calling x.zipWithIndex, which returns a new collection of tuples, and are then transforming that collection. This won't have any effects on the underlying array.

I can't think offhand of anything that would allow you to modify the array in place while still having access to the indices. If however, you can adopt the more functional style of returning a new collection, you could do something like the following:

val cal = Array.ofDim[Double](300, 10000) map { x =>
    x.zipWithIndex map (y => x(y._2) + 7)
};

In fact since cal is mutable in your example, you could do the same thing through reassignment. Not that I would encourage mutable variables if it can at all be avoided.

Sign up to request clarification or add additional context in comments.

Comments

2

To do the update in place, you can do it in a java-ish way like this:

for( y <- 0 until cal.length; 
     row <- cal( y );
     x <- 0 until row.length ) 
{
  row( x ) = some value // here you can get the indexes through (x, y)
}

// or

for( (row, y) <- cal.zipWithIndex; 
     x <- 0 until row.length ) 
{
  row( x ) = some value // here you can get the indexes through (x, y)
}

Comments

0

The easiest solution if you cannot find a function in the standard library is to write your own, especially if it's a simple one. There's nothing magical about functions as arguments in Scala that prevents you from doing that yourself.

Implicit classes even allow you to emulate the normal calling conventions. For example:

import scala.collection.mutable._

object Extensions {
  implicit class ExtMutSeq[T](val seq: Seq[T]) extends AnyVal {
    def transform_indexed(f: (T, Int) => T) {
      for (i <- 0 until seq.length) {
        seq(i) = f(seq(i), i)
      }
    }
  }
}

object Program extends App {
  import Extensions._
  val a = ArraySeq(1,2,3,4)
  a.transform_indexed((item, pos) => if (pos % 2 == 0) 0 else item)
  println(a)
}

(Depending on what the actual type of your rows is, you may need to adjust the type of seq above.)

You get the dual benefits of abstraction and reuse. Abstraction because it allows you to encapsulate the concept of transformation with an index in a single place, reuse because you only have to write it once. And because it's short code, it's not really necessary to rely on the standard library for it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.