différence entre each.with_index et each_with_index en Ruby?

94

Je ne comprends vraiment pas la différence entre each.with_indexet each_with_index. Ils sont de types différents mais semblent identiques dans la pratique.

Stan
la source
6
Mis à part la légère différence qui with_indexpermet un indice de départ offset, with_indexon préfère généralement lorsqu'il est utilisé conjointement avec map, reduce, collect, etc. Bref, map.with_indexlit mieux que each_with_index.map. Dans un sens, lorsqu'il est utilisé avec map, c'est un substitut à la map_with_indexméthode inexistante .
Cary Swoveland

Réponses:

171

La with_indexméthode prend un paramètre facultatif pour décaler l'index de départ. each_with_indexfait la même chose, mais n'a pas d'index de départ optionnel.

Par exemple:

[:foo, :bar, :baz].each.with_index(2) do |value, index|
    puts "#{index}: #{value}"
end

[:foo, :bar, :baz].each_with_index do |value, index|
    puts "#{index}: #{value}"
end

Les sorties:

2: foo
3: bar
4: baz

0: foo
1: bar
2: baz
marée noire
la source
41

each_with_indexa été introduit dans Ruby plus tôt. with_indexa été introduit plus tard:

  1. pour permettre une utilisation plus large avec divers recenseurs.
  2. pour permettre à l'index de commencer à partir d'un nombre autre que 0.

Aujourd'hui, l'utilisation with_indexserait meilleure du point de vue de la généralité et de la lisibilité, mais du point de vue de l'accélération du code, each_with_indexfonctionne légèrement plus vite que each.with_index.

Lorsque vous pensez qu'une seule méthode peut être facilement exprimée par un chaînage simple de quelques méthodes, il est généralement vrai que la méthode unique est plus rapide que la chaîne. Comme pour un autre exemple de cela, reverse_eachfonctionne plus vite que reverse.each. Ces méthodes ont des raisons d'exister.

Sawa
la source
1
Pour être juste cependant, le décalage ne change pas l'index, il ajoute simplement un nombre à l'index. Lorsque vous vérifiez l'index après votre appel, vous constaterez qu'il n'est pas affecté. Bonnes notes comme d'habitude, @sawa
vgoff
2
Je ne pense pas que les performances devraient être différentes (du moins pas substantiellement). Dans l' reverseexemple, le reverserenvoie un autre tableau et non un énumérateur. S'il a renvoyé un énumérateur, cela n'aurait pas dû être plus lent avec une bonne implémentation.
akostadinov