Existe-t-il une liste/séquence intégrée qui se comporte comme map
et fournit également l'index de l'élément?
Je crois que vous cherchez 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
De: http://www.artima.com/forums/flat.jsp?forum=283&thread=243570
Vous avez aussi des variations comme:
for((e,i) <- List("Mary", "had", "a", "little", "lamb").zipWithIndex) println(i+" "+e)
ou:
List("Mary", "had", "a", "little", "lamb").zipWithIndex.foreach( (t) => println(t._2+" "+t._1) )
Utilisez . map in . zipWithIndex
val myList = List("a", "b", "c")
myList.zipWithIndex.map { case (element, index) =>
println(element, index)
s"${element}(${index})"
}
Résultat:
List("a(0)", "b(1)", "c(2)")
Les solutions proposées souffrent du fait qu'elles créent des collections intermédiaires ou introduisent des variables qui ne sont pas strictement nécessaires. En fin de compte, tout ce que vous avez à faire est de suivre le nombre d’étapes d’une itération. Cela peut être fait en utilisant memoizing. Le code résultant pourrait ressembler à
myIterable map (doIndexed(someFunction))
La fonction doIndexed
- englobe la fonction intérieure qui reçoit un index et les éléments de myIterable
. Cela vous est peut-être familier à partir de JavaScript.
Voici un moyen d'atteindre cet objectif. Considérez l'utilitaire suivant:
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)
}
}
C'est déjà tout ce dont vous avez besoin. Vous pouvez appliquer cela par exemple comme suit:
import TraversableUtil._
List('a','b','c').map(doIndexed((i, char) => char + i))
qui résulte dans la liste
List(97, 99, 101)
De cette façon, vous pouvez utiliser les fonctions habituelles de Traversable au détriment de l'encapsulation de votre fonction efficace. Le temps système est la création de l'objet mémoizing et du compteur qui s'y trouve. Sinon, cette solution est aussi bonne (ou mauvaise) en termes de mémoire ou de performances que d'utiliser map
non indexée. Prendre plaisir!
Il y a CountedIterator
dans 2.7.x (que vous pouvez obtenir à partir d'un itérateur normal avec .counted). Je crois que cela a été déconseillé (ou simplement supprimé) en 2.8, mais il est assez facile de lancer le vôtre. Vous devez être capable de nommer l'itérateur:
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)
Ou, en supposant que votre collection ait un temps d'accès constant, vous pouvez mapper la liste des index au lieu de la collection réelle:
val ls = List("a","b","c")
0.until(ls.length).map( i => doStuffWithElem(i,ls(i)) )
Utilisez .map in .zipWithIndex avec la structure de données 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"
}
Résultats
List(
Key: a - Value: hello with Index: 0,
Key: b - Value: world with Index: 1,
Key: c - Value: again with Index: 2
)
Si vous souhaitez également rechercher les valeurs de la carte (comme je le devais):
val ls = List("a","b","c")
val ls_index_map = ls.zipWithIndex.toMap