web-dev-qa-db-ja.com

一度に2つの配列を反復処理する「Rubyの方法」とは

解決する問題よりも構文の好奇心の方が多い...

同じ長さの2つの配列があり、一度に両方を反復処理したい-たとえば、特定のインデックスで両方の値を出力したい場合。

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

each_indexを使用して、次のように配列にインデックスを付けることができることを知っています。

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

Ruby wayはこれをより良くするためにありますか?何かlike this?

# 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
120
nfm
>> @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]]
260
John La Rooy

使用 - Array.Zip メソッド。ブロックを渡して、対応する要素を順番に繰り返し処理します。

21
Anurag

列挙子を使用して、2つの配列を一度に繰り返す別の方法があります。

2.1.2 :003 > enum = [1,2,4].each
 => #<Enumerator: [1, 2, 4]:each> 
2.1.2 :004 > enum2 = [5,6,7].each
 => #<Enumerator: [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

列挙子は、他の手法の中でも特に、無限級数、並列反復を可能にするため、上記で使用した例よりも強力です。

20
Donato

他の人が言ったa.Zip(b).each{|x,y| }に加えて、[a,b].transpose.each{|x,y| }と言うこともできます。ただし、余分な[a,b]配列を作成しているため、おそらくそれほど高速ではありません。

16

元の質問に関連して、値を循環させたい不等長さの配列を反復処理するために使用できます

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

およびRubyは

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

これにより、Zipを使用するだけで得られるnil値を節約できます。

14
xavriley

配列を扱う場合は、2つの配列を単純に圧縮するだけで十分に機能します。しかし、次のような終わらない列挙子を扱っている場合はどうでしょうか。

_enum1 = (1..5).cycle
enum2 = (10..12).cycle
_

Zipはすべての要素を評価して結合しようとするため、enum1.Zip(enum2)は失敗します。代わりに、これを行います:

_enum1.lazy.Zip(enum2)
_

そのlazyは、結果の列挙子を遅延評価することであなたを救います。

6
Justin

妥協し、#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] }
2
Robert Schaaf