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
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!
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).
(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
(alias to avoid: find_all)
Very useful when you need to filter (i.e. “select”) multiple values.
The contrary of
(alias to avoid: detect)
Very useful when you need to find a single value.
(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:
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.
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?. This is just a matter of personal taste: feel free to use whichever you want.
This is a funny one!
1 2 3
In practice I don’t use it very often though.
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.
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,
This is a typical job for
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
while true, but terser.
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 and submit a bug if you don’t agree. :–)