Quelle est la manière Ruby de parcourir deux tableaux à la fois?

Plus une curiosité de syntaxe qu’un problème à résoudre …

J’ai deux tableaux de même longueur et je veux les parcourir tous les deux en même temps, par exemple pour afficher leurs valeurs à un certain index.

@budget = [ 100, 150, 25, 105 ] @actual = [ 120, 100, 50, 100 ] 

Je sais que je peux utiliser each_index et index dans les tableaux comme ceci:

 @budget.each_index do |i| puts @budget[i] puts @actual[i] end 

Y a-t-il une manière Ruby de faire cela mieux? Quelque chose comme ça?

 # Obviously doesn't achieve what I want it to - but is there something like this? [@budget, @actual].each do |budget, actual| puts budget puts actual end 

 >> @budget = [ 100, 150, 25, 105 ] => [100, 150, 25, 105] >> @actual = [ 120, 100, 50, 100 ] => [120, 100, 50, 100] >> @budget.zip @actual => [[100, 120], [150, 100], [25, 50], [105, 100]] >> @budget.zip(@actual).each do |budget, actual| ?> puts budget >> puts actual >> end 100 120 150 100 25 50 105 100 => [[100, 120], [150, 100], [25, 50], [105, 100]] 

Utilisez la méthode Array.zip et transmettez-lui un bloc pour parcourir les éléments correspondants de manière séquentielle.

Il existe un autre moyen d’itérer deux tableaux à la fois en utilisant des énumérateurs:

 2.1.2 :003 > enum = [1,2,4].each => # 2.1.2 :004 > enum2 = [5,6,7].each => # 2.1.2 :005 > loop do 2.1.2 :006 > a1,a2=enum.next,enum2.next 2.1.2 :007?> puts "array 1 #{a1} array 2 #{a2}" 2.1.2 :008?> end array 1 1 array 2 5 array 1 2 array 2 6 array 1 4 array 2 7 

Les énumérateurs sont plus puissants que les exemples utilisés ci-dessus, car ils permettent, entre autres, des séries infinies, des itérations parallèles.

En plus de a.zip(b).each{|x,y| } a.zip(b).each{|x,y| } comme d’autres l’ont dit, vous pouvez aussi dire [a,b].transpose.each{|x,y| } [a,b].transpose.each{|x,y| } , ce qui me semble un peu plus symésortingque. Probablement pas aussi rapide puisque vous créez le tableau supplémentaire [a,b] .

Relatif à la question initiale, pour itérer sur des tableaux de longueur inégale où vous voulez que les valeurs circulent, vous pouvez utiliser

 [1,2,3,4,5,6].zip([7,8,9].cycle) 

et Ruby vous donnera

 [[1, 7], [2, 8], [3, 9], [4, 7], [5, 8], [6, 9]] 

Cela vous évite les valeurs nil que vous obtiendrez simplement en utilisant zip

Simplement zipper les deux tableaux fonctionne bien si vous traitez avec des tableaux. Mais que se passe-t-il si vous avez affaire à des énumérateurs sans fin, tels que ceux-ci:

 enum1 = (1..5).cycle enum2 = (10..12).cycle 

enum1.zip(enum2) échoue car zip essaie d’évaluer tous les éléments et de les combiner. Au lieu de cela, faites ceci:

 enum1.lazy.zip(enum2) 

Celui qui lazy vous sauve en faisant en sorte que l’énumérateur résultant soit paresseux.

Que diriez-vous de compromettre et d’utiliser #each_with_index?

 include Enumerable @budget = [ 100, 150, 25, 105 ] @actual = [ 120, 100, 50, 100 ] @budget.each_with_index { |val, i| puts val; puts @actual[i] }