web-dev-qa-db-ger.com

Wie kann ich eine Karte verwenden und auch einen Index in Scala erhalten?

Gibt es eine eingebaute Liste/Sequenz, die sich wie map verhält und auch den Index des Elements bereitstellt?

89
Geo

Ich glaube, Sie suchen nach 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

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

Sie haben auch Variationen wie: 

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

oder:

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

Verwenden Sie . map in . zipWithIndex

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

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

Ergebnis:

List("a(0)", "b(1)", "c(2)")
45
Paulo Cheque

Die vorgeschlagenen Lösungen leiden unter der Tatsache, dass sie Zwischensammlungen erstellen oder Variablen einführen, die nicht unbedingt erforderlich sind. Letztendlich müssen Sie lediglich die Anzahl der Schritte einer Iteration nachverfolgen. Dies kann mithilfe von Memoizing erfolgen. Der resultierende Code könnte so aussehen

myIterable map (doIndexed(someFunction))

Die doIndexed- Funktion umschließt die innere Funktion, die sowohl einen Index als auch die Elemente von myIterable empfängt. Dies ist Ihnen möglicherweise von JavaScript bekannt.

Hier ist ein Weg, um diesen Zweck zu erreichen. Betrachten Sie das folgende Dienstprogramm:

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

Das ist schon alles was Sie brauchen. Sie können dies beispielsweise wie folgt anwenden:

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

was ergibt sich in der Liste

List(97, 99, 101)

Auf diese Weise können Sie die üblichen Traversable-Funktionen auf Kosten Ihrer effektiven Funktion verwenden. Der Overhead ist die Erstellung des Memo-Objekts und des Zählers darin. Andernfalls ist diese Lösung hinsichtlich des Arbeitsspeichers oder der Leistung genauso gut (oder schlecht) wie die Verwendung der nicht indizierten Variable map. Genießen!

8
Matt Brasen

Es gibt CountedIterator in 2.7.x (das Sie von einem normalen Iterator mit .counted erhalten können). Ich glaube, es ist in 2.8 veraltet (oder einfach entfernt worden), aber es ist leicht genug, selbst zu rollen. Sie müssen den Iterator benennen können:

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
Rex Kerr

Wenn Ihre Sammlung jedoch über eine konstante Zugriffszeit verfügt, können Sie anstelle der tatsächlichen Sammlung die Liste der Indizes zuordnen.

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

Verwenden Sie .map in .zipWithIndex mit Map-Datenstruktur

val sampleMap = Map("a" -> "hello", "b" -> "world", "c" -> "again")

val result = sampleMap.zipWithIndex.map { case ((key, value), index) => 
    s"Key: $key - Value: $value with Index: $index"
}

Ergebnisse

 List(
       Key: a - Value: hello with Index: 0, 
       Key: b - Value: world with Index: 1, 
       Key: c - Value: again with Index: 2
     )
0
fgfernandez0321

Wenn Sie auch nach den Kartenwerten suchen müssen (wie ich es musste):

val ls = List("a","b","c")
val ls_index_map = ls.zipWithIndex.toMap 
0
Yair Beer