Comment puis-je utiliser map et recevoir un index aussi bien dans Scala?
Existe-t-il une liste/séquence intégrée qui se comporte comme map
et fournit également l'index de l'élément?
5 réponses
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
À Partir de: http://www.artima.com/forums/flat.jsp?forum=283&thread=243570
Vous avez aussi des variantes 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) )
Utilisation . Carte dans .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. Pour en fin de compte tout ce que vous devez faire est de garder une trace du nombre d'étapes d'une itération. Cela peut être fait en utilisant la mémorisation. Le code résultant pourrait ressembler à
myIterable map (doIndexed(someFunction))
La Fonction doIndexed
enveloppe la fonction intérieure qui reçoit à la fois un index et les éléments de myIterable
. Cela pourrait vous être familier à partir de JavaScript.
Voici un façon d'atteindre ce but. 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 l'appliquer par exemple comme suit:
import TraversableUtil._
List('a','b','c').map(doIndexed((i, char) => char + i))
Qui aboutit à la liste
List(97, 99, 101)
De cette façon, vous pouvez utiliser les fonctions traversables habituelles au détriment de l'emballage de votre fonction effective. La surcharge est la création de l'objet de mémorisation et du compteur qui s'y trouve. Sinon, cette solution est aussi bonne (ou mauvaise) en termes de mémoire ou de performance que d'utiliser unindexed map
. Amusez-vous bien!
Il y a {[1] } dans 2.7.x (que vous pouvez obtenir à partir d'un itérateur .compter). Je crois qu'il a été déprécié (ou simplement supprimé) en 2.8, mais il est assez facile de rouler 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 a 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)) )