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

前端 未结 3 2067
时光说笑
时光说笑 2020-12-14 01:42

Let\'s consider a simple mapping example:


  val a = Array(\"One\", \"Two\", \"Three\")
  val b = a.map(s => myFn(s))

What I need is to use

相关标签:
3条回答
  • 2020-12-14 01:52

    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 + i
    myFun: (s: String, i: Int)java.lang.String
    
    scala> Array("nami", "zoro", "usopp")
    res17: Array[java.lang.String] = Array(nami, zoro, usopp)
    
    scala> res17.iterator.zipWithIndex
    res19: java.lang.Object with Iterator[(java.lang.String, Int)]{def idx: Int; def idx_=(x$1: Int): Unit} = non-empty iterator
    
    scala> res19 map { case (k, v) => myFun(k, v) }
    res22: Iterator[java.lang.String] = non-empty iterator
    
    scala> res22.toArray
    res23: 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)
    
    0 讨论(0)
  • 2020-12-14 02:03

    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;} )
    
    0 讨论(0)
  • 2020-12-14 02:10

    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 = 0
    while (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.)

    0 讨论(0)
提交回复
热议问题