Как я могу использовать карту и получить индекс также в Scala?


есть ли встроенный список/последовательность, который ведет себя как map а также предоставляет индекс элемента?

5 88

5 ответов:

Я полагаю, вы ищете 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

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

У вас также есть варианты, такие как:

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

или:

List("Mary", "had", "a", "little", "lamb").zipWithIndex.foreach( (t) => println(t._2+" "+t._1) )

использовать .карта in .zipWithIndex

val myList = List("a", "b", "c")

myList.zipWithIndex.map { case (element, index) => 
   println(element, index) 
   s"${element}(${index})"
}

результат:

List("a(0)", "b(1)", "c(2)")

предлагаемые решения страдают от того, что они создают промежуточные коллекции или вводят переменные, которые не являются строго необходимыми. В конечном счете, все, что вам нужно сделать, это отслеживать количество шагов итерации. Это можно сделать с помощью запоминания. Полученный код может выглядеть как

myIterable map (doIndexed(someFunction))

The doIndexed - функция обертывает внутреннюю функцию, которая получает как индекс, так и элементы myIterable. Это может быть знакомо вам от Яваскрипт.

вот способ достижения этой цели. Рассмотрим следующую программу:

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

это уже все, что вам нужно. Вы можете применить это, например, следующим образом:

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

что приводит к списку

List(97, 99, 101)

таким образом, вы можете использовать обычные проходимые-функций за счет упаковки эффективная функция. Накладные расходы-это создание объекта memoizing и счетчика в нем. В противном случае это решение как хорошо (или плохо) с точки зрения памяти или производительности, как с помощью unindexed map. Наслаждайтесь!

здесь CountedIterator в 2.7.x (который вы можете получить от обычного итератора .рассчитанный.) Я считаю, что он был устаревшим (или просто удален) в 2.8, но его достаточно легко свернуть самостоятельно. Вы должны быть в состоянии назвать итератор:

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)

или, предполагая, что ваша коллекция имеет постоянное время доступа, вы можете сопоставить список индексов вместо фактической коллекции:

val ls = List("a","b","c")
0.until(ls.length).map( i => doStuffWithElem(i,ls(i)) )