How to get the element index when mapping an array in Scala? How to get the element index when mapping an array in Scala? arrays arrays

How to get the element index when mapping an array in Scala?


Depends whether you want convenience or speed.

Slow:

a.zipWithIndex.map{ case (s,i) => myFn(s,i) }

Faster:

for (i <- a.indices) yield myFn(a(i),i){ var i = -1; a.map{ s => i += 1; myFn(s,i) } }

Possibly fastest:

Array.tabulate(a.length){ i => myFn(a(i),i) }

If not, this surely is:

val b = new Array[Whatever](a.length)var i = 0while (i < a.length) {  b(i) = myFn(a(i),i)  i += 1}

(In Scala 2.10.1 with Java 1.6u37, if "possibly fastest" is declared to take 1x time for a trivial string operation (truncation of a long string to a few characters), then "slow" takes 2x longer, "faster" each take 1.3x longer, and "surely" takes only 0.5x the time.)


A general tip: Use .iterator method liberally, to avoid creation of intermediate collections, and thus speed up your computation. (Only when performance requirements demand it. Or else don't.)

scala> def myFun(s: String, i: Int) = s + imyFun: (s: String, i: Int)java.lang.Stringscala> Array("nami", "zoro", "usopp")res17: Array[java.lang.String] = Array(nami, zoro, usopp)scala> res17.iterator.zipWithIndexres19: java.lang.Object with Iterator[(java.lang.String, Int)]{def idx: Int; def idx_=(x$1: Int): Unit} = non-empty iteratorscala> res19 map { case (k, v) => myFun(k, v) }res22: Iterator[java.lang.String] = non-empty iteratorscala> res22.toArrayres23: Array[java.lang.String] = Array(nami0, zoro1, usopp2)

Keep in mind that iterators are mutable, and hence once consumed cannot be used again.


An aside: The map call above involves de-tupling and then function application. This forces use of some local variables. You can avoid that using some higher order sorcery - convert a regular function to the one accepting tuple, and then pass it to map.

scala> Array("nami", "zoro", "usopp").zipWithIndex.map(Function.tupled(myFun))res24: Array[java.lang.String] = Array(nami0, zoro1, usopp2)


What about this? I think it should be fast and it's pretty. But I'm no expert on Scala speed...

a.foldLeft(0) ((i, x) => {myFn(x, i); i + 1;} )