The Ruby Enumerable#each method is the most simplistic and popular way to iterate individual items in an array. It accepts two arguments: the first being an enumerable list, and the second being a block. It takes each element in the provided list and executes the block, taking the current item as a parameter.
This can be done in a few ways in Ruby. The first is the plus operator. This will append one array to the end of another, creating a third array with the elements of both. Alternatively, use the concat method (the + operator and concat method are functionally equivalent).
The each{} method allows one loop through the elements of an array to perform operations on them. It is an enumerator function that allows you to iterate over elements of an array and returns an array.
>> @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]]
Use the Array.zip
method and pass it a block to iterate over the corresponding elements sequentially.
There is another way to iterate over two arrays at once using enumerators:
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
Enumerators are more powerful than the examples used above, because they allow infinite series, parallel iteration, among other techniques.
In addition to a.zip(b).each{|x,y| }
as others have said, you can also say [a,b].transpose.each{|x,y| }
, which strikes me as a tiny bit more symmetrical. Probably not as fast, though, since you're creating the extra [a,b]
array.
Related to the original question, for iterating over arrays of unequal length where you want the values to cycle around you can use
[1,2,3,4,5,6].zip([7,8,9].cycle)
and Ruby will give you
[[1, 7], [2, 8], [3, 9], [4, 7], [5, 8], [6, 9]]
This saves you from the nil
values that you'll get from just using zip
Simply zipping the two arrays together works well if you are dealing with arrays. But what if you are dealing with never-ending enumerators, such as something like these:
enum1 = (1..5).cycle
enum2 = (10..12).cycle
enum1.zip(enum2)
fails because zip
tries to evaluate all the elements and combine them. Instead, do this:
enum1.lazy.zip(enum2)
That one lazy
saves you by making the resulting enumerator lazy-evaluate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With