How can I use the map and get the index, as well as in Scala?

Is there a built-in List / Sequence module that behaves like a map and also provides an element index?

+95
scala functional-programming map
Feb 06 '10 at 13:59
source share
5 answers

I believe you are looking for zipWithIndex?

 scala> val ls = List("Mary", "had", "a", "little", "lamb") scala> ls.zipWithIndex.foreach{ case (e, i) => println(i+" "+e) } 0 Mary 1 had 2 a 3 little 4 lamb 

From: http://www.artima.com/forums/flat.jsp?forum=283&thread=243570

You also have options such as:

 for((e,i) <- List("Mary", "had", "a", "little", "lamb").zipWithIndex) println(i+" "+e) 

or

 List("Mary", "had", "a", "little", "lamb").zipWithIndex.foreach( (t) => println(t._2+" "+t._1) ) 
+140
Feb 06 2018-10-06T00
source share

Use a card . zipWithIndex

 val myList = List("a", "b", "c") myList.zipWithIndex.map { case (element, index) => println(element, index) s"${element}(${index})" } 

Result:

 List("a(0)", "b(1)", "c(2)") 
+50
Sep 04 '14 at 21:09
source share

The proposed solutions are related to the fact that they create intermediate collections or introduce variables that are not strictly necessary. Ultimately, all you have to do is keep track of the number of iteration steps. This can be done using memoizing. The resulting code may look like

 myIterable map (doIndexed(someFunction)) 

doIndexed -Funk wraps an internal function that receives both the index and myIterable elements. This may be familiar to you with JavaScript.

Here is a way to achieve this. Consider the following utility:

 object TraversableUtil { class IndexMemoizingFunction[A, B](f: (Int, A) => B) extends Function1[A, B] { private var index = 0 override def apply(a: A): B = { val ret = f(index, a) index += 1 ret } } def doIndexed[A, B](f: (Int, A) => B): A => B = { new IndexMemoizingFunction(f) } } 

That is all you need. You can apply this, for example, as follows:

 import TraversableUtil._ List('a','b','c').map(doIndexed((i, char) => char + i)) 

leading to a list

 List(97, 99, 101) 

This way you can use regular Traversable functions by porting your efficient function. Overhead is the creation of a memoizing object and a counter in it. Otherwise, this solution will be as good (or bad) in terms of memory or performance as using a unindexed map . Enjoy it!

+8
May 09 '12 at 9:41 a.m.
source share

2.7.x has a CountedIterator (which you can get from a regular iterator with .counted). I believe that it was obsolete (or simply deleted) at 2.8, but it is quite simple to collapse. You should be able to name an iterator:

 val ci = List("These","are","words").elements.counted scala> ci map (i => i+"=#"+ci.count) toList res0: List[java.lang.String] = List(These=#0,are=#1,words=#2) 
+5
Feb 06 2018-10-06
source share

Or, if your collection has constant access time, you can match the list of indexes instead of the actual collection:

 val ls = List("a","b","c") 0.until(ls.length).map( i => doStuffWithElem(i,ls(i)) ) 
+3
Mar 12 2018-12-12T00:
source share



All Articles