Ruby Array Iterators
Here we will cover the differences and use cases for Array#each
, Array#map
, and Array#select
.
What is the difference?
Array#each
is used for iteration. #each
is preferred by Rubyists in place of using a for loop
. When a block is passed as an argument, each
invokes the block once for each element of the array and returns the original array that it was invoked on.
Array#each
does not consider the return value of the block.
If no block is passed, it returns an enumerator. It does not mutate the caller (the original array is left unmodified).
Array#map
is used for transformation. When a block is passed as an argument, map
invokes the block once for each element in the array. The difference of map
and each
lie in the return value. Array#map
returns a new array that contains the values returned by the block.
Array#map
considers the return value of the block. When no block is passed, it returns an enumerator. It does not mutate the caller (the original array is left unmodified).
Array#select
is used for filtering, it is used to select items in the original collection. Just like Array#each
and Array#map
, Array#select
invokes the block once for each element of the array, but unlike them it is then returning a new array containing elements that the block evaluate as true or that is truthy.
Array#select
considers the truthiness of the return value of the block.
If no block is passed, it returns an enumerator. It does not mutate the caller (the original array is left unmodified).
Ruby — Array#each
Calls the passed block once for each element in self, passing that element as an argument. Then it returns the original Array. — Ruby Documentation
What does this mean?
Lets dive into an example to find out…
Array#each
is a collection iterator, in this case an array iterator. When passed a block, #each
calls the block once for each element in the array. It passes each element as an argument. It starts with the first element and ends with the last element and returns self
ie, the original array.
[“foo”, “bar”, “bazz”].each { |str| p str }# First iteration outputs:
#=> "foo"# Second iteration outputs:
#=> "bar"# Third iteration outputs:
#=> "bazz"# Returns:
#=> [“foo”, “bar”, “bazz”]
Here the first iteration outputs "foo”
.
Why?
The each
method calls the passed block for each element in the array passing each element as an argument to the block.
The second iteration, bar
is output.
The third iteration, bazz
is output.
Now that each has passed every element in the array, it returns the original array. #=> [“foo”, “bar”, “bazz”]
Ruby — Array#map
Invokes the passed block once for each element of
self
.Creates a new array containing the values returned by the block. — Ruby Documentation
To make the above more explicit…
Array#map
is an array iterator method. Its action is transformation. When #map
is passed a block, it invokes the block once for each element within the array. #map
returns a new array containing the values that were returned by the block.
[“foo”, “bar”, “bazz”].map {|str| str.capitalize }# First iteration:
#=> "Foo"# Second iteration:
#=> "Bar"# Third iteration:
#=> "Bazz"# Returns:
#=> ["Foo", “Bar”, “Bazz”]
Since we are not outputting anything in our block arguments, the first through third iterations will be happening behind the scenes and we will only be seeing the return value. I have however included the above first through third iterations so you can see what is happening behind the scenes.
First iteration, Array#map
invokes the block passing the first element to the block, and #capitalize
is called on the string object “foo”.
Second iteration, Array#map
invokes the block passing the second element to the block, and #capitalize
is called on the string object “bar”.
Third iteration, Array#map
invokes the block passing the third element to the block, and #capitalize
is called on the string object “bazz”.
Here Array#map
has come to the end of the original array and returns a new array containing the values returned by the block :
#=> [“Foo”, “Bar”, “Bazz”]
Ruby — Array#select
Returns a new array containing all elements of
ary
for which the passedblock
returns a true value. — Ruby Documentation
Array#select
is a selection iterator that is used as a filter. Array#select
invokes the block once for each element of the array. It considers the return value of the block based on its truthiness and returns a new array the length of the original or less.
[1,2,3,4].select { |num| num.even? }
# First iteration (return value of block):
#=> false# Second iteration (return value of block):
#=> true# Third iteration (return value of block):
#=> false# Fourth iteration (return value of block):
#=> true# Returns (return value of #select):
#=> [2,4]
First iteration, Array#select
invokes the block passing the first element to the block, and #even?
is called on the Integer 1
which returns false.
Second iteration, Array#select
invokes the block passing the second element to the block, and #even?
is called on the Integer 2
which returns true.
Third iteration, Array#select
invokes the block passing the third element to the block, and #even?
is called on the Integer 3
which returns false.
Fourth iteration, Array#select
invokes the block passing the fourth element to the block, and #even?
is called on the Integer 4
which returns true.
Array#select
now returns a new array containing each respective element of the original array that the block returned which either evaluated as true or is truthy
.#=> [2,4]