web-dev-qa-db-fra.com

Ruby each_with_index offset

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

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

Modifier:

Précision: je ne veux pas d’un offset de tableau, je veux que l’indice dans l’index each_with_index ne commence pas à 0 mais par ex. 1.

81
Mark

Réellement, Enumerator#with_index reçoit l'offset comme paramètre optionnel:

[: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 ce n'est là que dans 1.9.2.

107
Mladen Jablanović

Ce qui suit est succinct, utilisant la classe Ruby's Enumerator.

[: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.

47
Zack Xu

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

4
Andrew Grimm

Je suis tombé dessus.

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

Dans la vue itération:

il suffit d'ajouter: index + 1

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

4
Ariel De La Rosa

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

De plus, je devrais remarquer que si le décalage est supérieur à la taille de votre tableau, il provoquera 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 prévaloir offset:

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

C'est petit hacky

PD 2

En ce qui concerne la mise à jour de votre question, vous n'avez plus besoin de tableau, mais d'un index pour que la solution @sawa fonctionne correctement.

3
fl00r

Cela fonctionne dans chaque version 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
1
fotanus

Ariel a raison. C'est la meilleure façon 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.

1
boulder_ruby

Une autre approche consiste à utiliser 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) }
1
Andrew Grimm
offset = 2
some_array[offset..-1].each_with_index{|item, index| some_func(item, index+offset) }
0
ipsum