Enumerable: Go Fetch!
This is part of the Back to Basics series.
See the introductory article for an explanation of why this series is important.
Last time, on “Enumerable: Scratching that Each” (way back in 2019), we learned about the 65 different versions of each
and when and how to use …er… each of them.
This time we are going to work on various ways of fetching simple sequences of elements from an enumerable object.
Here is a quick summary:
to_a
, akaentries
first
take(n)
, akafirst(n)
drop(n)
take_while { |item| ... }
drop_while { |item| ... }
Let’s start with the simplest task: return all the items in a collection.
to_a
or its alias entries
does just that:
class PocketContentGuesses
include Enumerable
def each
yield "handses"
yield "knife"
yield "string", "nothing"
end
end
p PocketContentGuesses.new.to_a
["handses", "knife", ["string", "nothing"]]
Doesn’t come up too often unless you need to serialize a collection as an array somewhere.
Next, let’s just get the first
item in the collection:
%w[a b c d].first # => "a"
Note that if the collection is empty, you get nil
:
[].first #=> nil
Let’s step it up a notch. What if we want to get the first n
elements from a collection (where n
is a non-negative number)?
take(n)
, aka first(n)
returns this new array:
%w[a b c d].take(2) #=> %w[a b]
If you “take” 0
elements, you get an empty array:
%w[a b c d].first(0) #=> []
If you “take” a number that is more than the number of elements in the collection, you just get the whole collection:
%w[a b c d].take(10) #=> %w[a b c d]
Cool. What if we want to skip n
elements from a collection, then return the remainder?
drop(n)
returns this new array:
%w[a b c d].drop(2) #=> %w[c d]
If you “drop” 0
elements, you get the full collection back as a new array (similar to to_a
)
%w[a b c d].drop(0) #=> %w[a b c d]
If you “drop” too many elements, you get an empty array back.
%w[a b c d].drop(4) #=> []
Both of these “take” and “drop” concepts also have a block form.
take_while { |item| ... }
“takes” elements while the given block returns a truthy value:
[1, 1, 2, 3, 5, 8].take_while { |item| item.odd? } #=> [1, 1]
If all of the items in the list return true
from the block, then you get the full collection back as an array (just like to_a
or take(10)
):
[1, 1, 2, 3, 5, 8].take_while(&:positive?) #=> [1, 1, 2, 3, 5, 8]
If the first item in the list returns false
from the block, then you get an empty array:
[1, 1, 2, 3, 5, 8].take_while(&:even?) #=> []
drop_while { |item| ... }
“drops” elements while the given block returns a truthy value, and returns the remainder as an array:
[1, 1, 2, 3, 5, 8].drop_while { |item| item.odd? } #=> [2, 3, 5, 8]
If all of the items in the list return true
from the block, then you get an empty array back:
[1, 1, 2, 3, 5, 8].drop_while(&:positive?) #=> []
If the first item in the list returns false
from the block, then you get the full collection back as an array (just like to_a
or drop(0)
):
[1, 1, 2, 3, 5, 8].drop_while(&:even?) #=> [1, 1, 2, 3, 5, 8]
To read the rest of the series: click here