Gibt es eine eingebaute Liste/Sequenz, die sich wie map
verhält und auch den Index des Elements bereitstellt?
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) )
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)")
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!
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)
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)) )
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
)
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