The Return of Enumerating Enumerable
Back in January, I wrote that although the Ruby documentation site RubyDoc.org was useful, I found its writing unclear or confusing and some of its entries lacking in important information. In the “do it yourself and share it afterwards” spirit of open source, I started cataloguing the methods in Ruby’s workhorse module, Enumerable
in a series of articles called Enumerating Enumerable. Enumerable
is a pretty good place to start: its methods are often used and RubyDoc.org’s writeups of its methods are sparse (and in some cases, barely intelligible), especially when it comes to applying them to hashes.
In observance of another spirit of open source — that part that makes me sometimes yell “Free as in crap!” — I dropped the ball. There’s nothing like a little company turbulence and a sudden and very complete change in jobs to completely throw a wrench in a not-for-profit, self-driven, spare-time scratch-an-itch project like Enumerating Enumerable. Each time I started to write a new installment of Enumerating Enumerable, something would come up and I’d say “I’ll write it later.” As you know, later often turns into never.
I’ve been meaning to bring programming articles back to Global Nerdy for some time. In spite of the fact that my career track has been taking me away from day-to-day programming, I still plan to keep my skills sharp with writing development articles and working on hobby coding projects. With the RubyFringe conference coming up (I’m MCing the first evening’s commencement event) and my feeling a bit Ruby-rusty, I thought “What better time than now to reboot the Enumerating Enumerable series?”
So here begins version 2.0 of Enumerating Enumerable. I’ll be working my way through Enumerable
‘s methods in alphabetical order, from Enumerable#all?
to Enumerable#zip
, each method covered for both arrays and hashes as well as special cases, supplemented with easy-to-grasp tables and graphics. I hope you find it useful!
Enumerable#all? Quick Summary
In the simplest possible terms | Do all items in the collection meet the given criteria? |
---|---|
Ruby version | 1.8 and 1.9 |
Expects | A block containing the criteria. This block is optional, but you’re likely to use one in most cases. |
Returns | true if all the items in the collection meet the given criteria.
|
RubyDoc.org’s entry | Enumerable.all? |
Enumerable#all? and Arrays
When used on an array and a block is provided, all?
passes each item to the block. If the block never returns false
or nil
during this process, all?
returns true
; otherwise, it returns false
.
# "feta" is the shortest-named cheese in this list cheeses = ["feta", "cheddar", "stilton", "camembert", "mozzarella", "Fromage de Montagne de Savoie"] cheeses.all? {|cheese| cheese.length >= 4} => true cheeses.all? {|cheese| cheese.length >= 5} => false
When the block is omitted, all?
uses this implied block: {|item| item}
. Since everything in Ruby evaluates to true
except for false
and nil
, using all?
without a block is effectively a test to see if all the items in the collection evaluate to true
(or conversely, if there are any false
or nil
values in the array).
cheeses.all? => true cheeses << false => ["feta", "cheddar", "stilton", "camembert", "mozzarella", "Fromage de Montagne de Savoie", false] cheeses.all? => false
Enumerable#all? and Hashes
When used on a hash and a block is provided, all?
passes each key/value pair as a two-element array to the block, which you can “catch” as either:
- A two-element array, with the key in element 0 and its corresponding value in element 1, or
- Two separate items, the first being the key, the second being the corresponding value.
If the block never returns false
or nil
during this process, all?
returns true
; otherwise, it returns false
.
# Here's a hash where for each key/value pair, the key is a programming language and # the corresponding value is the year when that language was first released # The keys range in value from "Javascript" to "Ruby", and the values range from # 1987 to 1996 languages = {"Javascript" => 1996, "PHP" => 1994, "Perl" => 1987, "Python" => 1991, "Ruby" => 1993} languages.all? {|language| language[0] >= "Delphi"} => true languages.all? {|language, year_created| language >= "Delphi"} => true languages.all? {|language| language[0] >= "Visual Basic"} => false languages.all? {|language, year_created| language >= "Visual Basic"} => false languages.all? {|language| language[0] >= "Delphi" and language[1] <= 2000} => true languages.all? {|language, year_created| language >= "Delphi" and year_created <= 2000} => true languages.all? {|language| language[0] >= "Delphi" and language[1] > 2000} => false languages.all? {|language, year_created| language >= "Delphi" and year_created > 2000} => false
Using all?
without a block on a hash is meaningless, as it will always return true
. When the block is omitted, all?
uses this implied block: {|item| item}
. In the case of a hash, item
will always be a two-element array, which means that it will never evaluate as false
nor nil
.
And yes, even this hash, when run through all?
, will still return true
:
{false => false, nil => nil}.all? => true
Special Case: Using Enumerable#all? on Empty Arrays and Hashes
When applied to an empty array or hash, with or without a block, all?
always returns true
. That’s because with an empty collection, there are no values to process and return a false
value.
Let’s look at the case of empty arrays:
cheeses = [] => [] cheeses.all? {|cheese| cheese.length >= 4} => true cheeses.all? => true # Let's try applying "all?" to a non-empty array # using a block that ALWAYS returns false: ["Gruyere"].all? {|cheese| false} => false # ...but watch what happens when we try the same thing # with an EMPTY array! [].all? {|cheese| false} => true
…now let’s look at the case of empty hashes:
languages = {} => {} languages.all? {|language| language[0] >= "Delphi"} => true languages.all? {|language, year_created| language >= "Delphi"} => true languages.all? => true # Let's try applying "all?" to a non-empty hash # using a block that ALWAYS returns false: {"Lisp" => 1959}.all? {|language| false} => false # ...but watch what happens when we try the same thing # with an EMPTY hash! {}.all? {|language| false} => true
18 replies on “Enumerating Enumerable: Enumerable#all?”
[…] Welcome to the second installment of Enumerating Enumerable, my project to do a better job of documenting Ruby’s Enumerable module than RubyDoc.org. This installment will cover Enumerable#any?, which I like to think of as Enumerable.all?’s more easy-going cousin (I covered Enumerable.all? in the previous installment). […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
[…] all? […]
This is very helpful. I’ve been avoiding Enumerables because I never quite got what they were. It’s cool to finally have a clear description. Good job!
[…] niceties), but I have no excuse for blowing this. I’ve actually written a whole series of articles on the power of Ruby’s Enumerable module, including the select method (and what I […]