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 définitive, il suffit de garder la trace du nombre d'étapes d'une itération. Ceci peut être fait en utilisant la mémorisation. Le code résultant pourrait ressembler à
myIterable map (doIndexed(someFunction))
Le site doIndexed
-La fonction enveloppe la fonction intérieure qui reçoit à la fois un indice et les éléments de myIterable
. Cela vous est peut-être familier avec JavaScript.
Voici un moyen d'atteindre cet objectif. Considérons 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))
ce qui donne la liste
List(97, 99, 101)
De cette façon, vous pouvez utiliser les fonctions Traversable habituelles au prix de l'enveloppement de votre fonction effective. La surcharge est la création de l'objet de mémorisation et du compteur qu'il contient. Autrement, cette solution est aussi bonne (ou mauvaise) en termes de mémoire ou de performance que l'utilisation de fonctions non indexées. map
. Profitez-en !