Ruby Enumerable, Part 2
August 06, 2014
The Enumerable module can be used for all of your Ruby classes as long as they implement their own each method. A good example of this are the Active Record Collection Objects. The Rails team has each defined in ActiveRecord.
each
#each
can be implemented on any object and what it does is it iterates through a collection and performs the block on each element of the collection.
User.all.each { |user| puts user.email }
charlesdmassry@gmail.com
wombat@example.com
For every method in Enumerable, it turns to #each
for every method and uses each to perform the method.
each_cons
#each_cons
returns a group of arrays of consecutive indices with the length specified by the number in the parameter. It then performs the block operation on each array.
[1, 2, 3, 4].each_cons(2) { |a| p a }
[1, 2]
[2, 3]
[3, 4]
{ name: 4, age: 5, ssn: 6 }.each_cons(2) { |a| p a }
[[:name, 4], [:age, 5]]
[[:age, 5], [:ssn, 6]]
One collection is turned into an array that contains the number of objects in an argument and performs the operation of the block on each array.
each_entry
#each_entry
you can just use #each
for similar results.
each_slice
#each_slice
takes an argument and similar to #each_cons
, performs an operation on a new sub-array. This method however, doesn’t make consecutive arrays but makes slices of arrays.
[1, 2, 3, 4].each_cons(2) { |a| p a }
[1, 2]
[3, 4]
{ name: 4, age: 5, ssn: 6 }.each_cons(2) { |a| p a }
[[:name, 4], [:age, 5]]
[[:ssn, 6]]
Here you can see it can return an uneven output for mismatched elements.
eachwithindex
#each_with_index
performs each on the collection and also keeps track of the current index.
user = []
%w(name age ssn).each_with_index do |element, index|
user << element * index
end
["", "age", "ssnssn"]
It can be used for a lot more complicated operations that this and will make your code a lot nicer that this.
user = []
count = 0
%w(name age ssn).each do |element|
user << element
count += 1
end
eachwithobject
#each_with_object
works by taking a block and a parameter and performing the block operation on the current element and the parameter.
(1..3).each_with_object([]) { |a, i| p a, i }
1
[]
2
[]
3
[]
This method can be used almost identically to #each
.
numbers = [1,2,6]
(1..3).each_with_object(numbers) { |a, i| i << a } #=> [1, 2, 6, 1, 2, 3]
The second element in the block argument here is the parameter.
entries
#entries
can be used as an alias for #to_a
. In some instances, it reads a little bit better than #to_a
.
find
#find
returns the first entry where the block conditions are true. It is aliased to detect.
[1,2,5,7,6].find { |a| a > 5 } #=> 7
As you can see, #find
returns an a number for the first one it finds, for this example it is 7 and not 6 because of the ordered array, so it breaks out. Generally, it would be a good idea to sort this array first if you are using the find method.
find_all
#find_all
is similar to #find
except it returns an array where the given conditions are true.
[1,2,5,7,6].find_all { |a| a > 5 } #=> [7, 6]
find_index
#find_index
returns the index of #find
.
[1,2,5,7,6].find_index { |a| a > 5 } #=> 3
Here it would find the number 7 and see that it is at index 3 and return that number. Stay tuned for more.