Risposte:
Credo che stai cercando 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
Da: http://www.artima.com/forums/flat.jsp?forum=283&thread=243570
Hai anche varianti come:
for((e,i) <- List("Mary", "had", "a", "little", "lamb").zipWithIndex) println(i+" "+e)
o:
List("Mary", "had", "a", "little", "lamb").zipWithIndex.foreach( (t) => println(t._2+" "+t._1) )
whileciclo, che è probabilmente tra le opzioni più veloci.
viewte dovrebbe essere in grado di impedire la creazione e l'attraversamento di una lista extra.
Uso . mappa in. zipWithIndex
val myList = List("a", "b", "c")
myList.zipWithIndex.map { case (element, index) =>
println(element, index)
s"${element}(${index})"
}
Risultato:
List("a(0)", "b(1)", "c(2)")
mapcome richiesto invece di stampare solo all'interno di un file foreach.
Le soluzioni proposte soffrono del fatto che creano collezioni intermedie o introducono variabili non strettamente necessarie. In definitiva, tutto ciò che devi fare è tenere traccia del numero di passaggi di un'iterazione. Questo può essere fatto usando la memorizzazione. Il codice risultante potrebbe essere simile a
myIterable map (doIndexed(someFunction))
La doIndexed-Function avvolge la funzione interior che riceve sia un indice che gli elementi di myIterable. Questo potrebbe esserti familiare da JavaScript.
Ecco un modo per raggiungere questo scopo. Considera la seguente utilità:
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)
}
}
Questo è già tutto ciò di cui hai bisogno. Puoi applicarlo ad esempio come segue:
import TraversableUtil._
List('a','b','c').map(doIndexed((i, char) => char + i))
che risulta nell'elenco
List(97, 99, 101)
In questo modo, puoi usare le solite funzioni Traversable a scapito di avvolgere la tua funzione effettiva. L'overhead è la creazione dell'oggetto memoizing e del contatore in esso contenuto. Altrimenti questa soluzione è buona (o cattiva) in termini di memoria o prestazioni come l'utilizzo di unindexed map. Godere!
coll.view.zipWithIndexposto dicoll.zipWithIndex
C'è CountedIteratorin 2.7.x (che puoi ottenere da un normale iteratore con .counted). Credo che sia stato deprecato (o semplicemente rimosso) nella 2.8, ma è abbastanza facile lanciarne uno tuo. Devi essere in grado di nominare l'iteratore:
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)
Oppure, supponendo che la tua raccolta abbia un tempo di accesso costante, potresti mappare l'elenco degli indici invece della raccolta effettiva:
val ls = List("a","b","c")
0.until(ls.length).map( i => doStuffWithElem(i,ls(i)) )
ls.indices.map(i => doStuffWithElem(i, ls(i))
indicesè implementato perché0 until length è più o meno la stessa cosa: P
Listera davvero scarso. Ho detto tuttavia che questo è adatto se la tua collezione ha un tempo di accesso costante. Avrei dovuto scegliere Array.
Usa .map in .zipWithIndex con la struttura dati Map
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"
}
Risultati
List(
Key: a - Value: hello with Index: 0,
Key: b - Value: world with Index: 1,
Key: c - Value: again with Index: 2
)
Ci sono due modi per farlo.
ZipWithIndex: crea automaticamente un contatore che inizia con 0.
// zipWithIndex with a map.
val days = List("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")
days.zipWithIndex.map {
case (day, count) => println(s"$count is $day")
}
// Or use it simply with a for.
for ((day, count) <- days.zipWithIndex) {
println(s"$count is $day")
}
L'output di entrambi i codici sarà:
0 is Sun
1 is Mon
2 is Tue
3 is Wed
4 is Thu
5 is Fri
6 is Sat
Zip : usa il metodo zip con uno stream per creare un contatore. Questo ti dà un modo per controllare il valore iniziale.
for ((day, count) <- days.zip(Stream from 1)) {
println(s"$count is $day")
}
Risultato:
1 is Sun
2 is Mon
3 is Tue
4 is Wed
5 is Thu
6 is Fri
7 is Sat
zipWithIndexmetodo per ottenere l'indice all'interno di un ciclo / mappa / qualunque cosa.