Ruby each_with_index offset

Puis-je définir le décalage de l’index dans l’iterator de boucle each_with_index? Ma tentative directe a échoué:

some_array.each_with_index{|item, index = 1| some_func(item, index) } 

Modifier:

Clarification: Je ne veux pas de décalage de tableau que je souhaite que l’index au sein de each_with_index ne commence pas par 0 mais par exemple 1.

Enumerator#with_index reçoit en fait un décalage en tant que paramètre facultatif:

 [:foo, :bar, :baz].to_enum.with_index(1).each do |elem, i| puts "#{i}: #{elem}" end 

les sorties:

 1: foo 2: bar 3: baz 

BTW, je pense que c’est là que dans 1.9.2.

Ce qui suit est succinct, en utilisant la classe Enumerator de Ruby.

 [:foo, :bar, :baz].each.with_index(1) do |elem, i| puts "#{i}: #{elem}" end 

sortie

 1: foo 2: bar 3: baz 

Array # chacun renvoie un énumérateur, et l’appel de Enumerator # with_index renvoie un autre énumérateur, auquel un bloc est transmis.

1) Le plus simple est de substituer l’ index+1 au lieu de l’ index à la fonction:

 some_array.each_with_index{|item, index| some_func(item, index+1)} 

mais ce n’est probablement pas ce que vous voulez.

2) La prochaine chose à faire est de définir un index j différent dans le bloc et de l’utiliser à la place de l’index original:

 some_array.each_with_index{|item, i| j = i + 1; some_func(item, j)} 

3) Si vous souhaitez utiliser l’index de cette manière souvent, définissez une autre méthode:

 module Enumerable def each_with_index_from_one *args, &pr each_with_index(*args){|obj, i| pr.call(obj, i+1)} end end %w(one two three).each_with_index_from_one{|w, i| puts "#{i}. #{w}"} # => 1. one 2. two 3. three 


Mettre à jour

Cette réponse, à laquelle il a été répondu il y a quelques années, est maintenant obsolète. Pour les Rubis modernes, la réponse de Zack Xu fonctionnera mieux.

Si some_index est en quelque sorte significatif, alors envisagez d’utiliser un hachage plutôt qu’un tableau.

Je l’ai rencontré.

Ma solution non nécessaire est la meilleure, mais cela a fonctionné pour moi.

Dans l’itération de la vue:

ajoutez simplement: index + 1

C’est tout pour moi, car je n’utilise aucune référence à ces index mais juste pour les afficher dans une liste.

Oui, vous pouvez

 some_array[offset..-1].each_with_index{|item, index| some_func(item, index) } some_array[offset..-1].each_with_index{|item, index| some_func(item, index+offset) } some_array[offset..-1].each_with_index{|item, index| index+=offset; some_func(item, index) } 

UPD

Aussi, je devrais remarquer que si offset est plus que la taille de votre tableau, il y aura une erreur. Car:

 some_array[1000,-1] => nil nil.each_with_index => Error 'undefined method `each_with_index' for nil:NilClass' 

Que pouvons-nous faire ici:

  (some_array[offset..-1]||[]).each_with_index{|item, index| some_func(item, index) } 

Ou pour compenser l’offset:

  offset = 1000 some_array[offset..-1].each_with_index{|item, index| some_func(item, index) } if offset < = some_array.size 

Ceci est peu pirate

UPD 2

Pour autant que vous ayez mis à jour votre question et que vous n’ayez plus besoin de décalage Array, mais de compensation d’index, la solution @sawa fonctionnera parfaitement pour vous.

Ariel a raison C’est le meilleur moyen de gérer cela, et ce n’est pas si mal

 ary.each_with_index do |a, i| puts i + 1 #other code end 

C’est parfaitement acceptable et meilleur que la plupart des solutions que j’ai vues pour cela. J’ai toujours pensé que c’était ce que #inject était pour … eh bien.

Une autre approche consiste à utiliser la map

 some_array = [:foo, :bar, :baz] some_array_plus_offset_index = some_array.each_with_index.map {|item, i| [item, i + 1]} some_array_plus_offset_index.each{|item, offset_index| some_func(item, offset_index) } 

Cela fonctionne dans toutes les versions de ruby:

 %W(one two three).zip(1..3).each do |value, index| puts value, index end 

Et pour un tableau générique:

 a.zip(1..a.length.each do |value, index| puts value, index end 
 offset = 2 some_array[offset..-1].each_with_index{|item, index| some_func(item, index+offset) }