If any of you have written code in the last year that had an explicit loop […], you don’t understand collections.
You may be baffled by this quote if you come from a C-flavored language such as C++ and Java,
where explicit loops like for
and foreach
are part of your everyday life.
Luckily, collection methods come built-in with Ruby. Once you realize how powerful they are compared to explicit loops, there is no going back!
each
Let’s begin with the collection method that has the least added value.
each
is the equivalent of a for
loop. Use it when you need to iterate on a collection with side effects.
1 2 3 |
|
For your information, Ruby also has a for
statement (nobody uses it though).
map
(alias to avoid: collect)
Whenever you need to transform some values into some other values, map
is your friend.
1 2 3 4 5 |
|
map
is your bread and butter. I probably use it more than each
.
select
(alias to avoid: find_all)
Very useful when you need to filter (i.e. “select”) multiple values.
1
|
|
reject
The contrary of select
1
|
|
partition
select
+ reject
1
|
|
find
(alias to avoid: detect)
Very useful when you need to find a single value.
1
|
|
reduce
(alias to avoid: inject)
reduce
is very important in functionnal programming, where it is also known as fold
.
Indeed, it can be used to build everything else: map
, select
, find
, min
, max
, sums, etc.
The idea is to use an accumulator that will contain the final result.
This accumulator can be anything: a number, an array, a hash, etc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
I rarely use reduce
in practice, but it is fun and good to know for your computer science culture.
all?
1
|
|
Self-explanatory.
any?
1
|
|
Self-explanatory.
By the way, I like using the “no block” form of any?
to ask if something “has any” significant element:
1 2 3 4 |
|
I find it more expressive than !some_array.empty?
.
times
This is a funny one!
1 2 3 |
|
In practice I don’t use it very often though.
Sorting methods
1 2 3 4 |
|
But… I want indexes!
On top of the current element, you also need the current index? Worry not, fellow citizen. Ruby has it all.
1 2 3 4 5 6 7 |
|
In practice I don’t use each_with_index
very often.
I never had to use map.with_index
, but I put it for the sake of being comprehensive.
Explicit loops
Collection methods will probably cover 90% of your needs.
What is certain is that you won’t need to use a for
loop ever again.
However, there are cases when the number of iterations in not known in advance:
if you work on an algorithm or low-level code, for example.
This is a typical job for while
and until
.
In this case, these explicit loops are ok to use.
1 2 3 4 5 6 7 8 9 |
|
You may want to use an infinite loop: for example the main infinite loop of a video game. Here is the syntax:
1 2 3 4 |
|
Same as while true
, but terser.
Going further
Ruby collection methods become even more powerful if you combine them:
1 2 3 4 5 |
|
Don’t do this to excess though!
This article covers the main collection methods: feel free to dive into the
Ruby Core documentation for more.
Finally, if you are wondering why I avoid aliases such as collect and inject, you can read this community-driven
Ruby style guide.