P is for Programming

Ruby map, collect and select

January 12, 2012

As a newcomer to Ruby, I have often been confused by the 3 very similar enumerators on the Array class: map, collect and select. Let’s try to figure this out using an example.

list = (1..10).to_a

p list
p list.collect { |i| i >= 3 && i <= 7 }
p list.map { |i| i >= 3 && i <= 7 }
p list.select { |i| i >= 3 && i <= 7 }

terminal output

All three methods have a similar signature and take a block parameter. The map and collect methods both return an array of values returned by the block. The select method will return the actual values being iterated over if the block evaluates to true. Here it is important to know that any Ruby object can be evaluated as a boolean. (Pretty much every object will evaluate to true except nil and false)

The previous example doesn’t really show how we would use map or collect – let’s try another example.

class Person
  attr_accessor :name, :surname, :age
  def initialize(name,surname,age)
    @name, @surname, @age = name, surname, age
  end
end

people = []
people << Person.new("Daniel","Craig",43)
people << Person.new("Pierce","Brosnan",58)
people << Person.new("Sean","Connery",81)

p people.map { |p| p.surname }

terminal output

Here the map method makes a bit more sense. So what’s the difference between the map and collect methods? Turns out, there is no difference. In fact, if you look at the Ruby Documentation you will see that under the hood both map and collect are implemented as the C rb_ary_collect method.

If you want to play around with my example you can find it here. Happy coding.

Tags: Ruby

  1. John says:

    Okay, so now I’m curious: in functional programming, you’ve got the equivalent of map (or .Select() in LINQ) and filter (or .Where() in LINQ). What is the Ruby equivalent of a fold (or .Aggregate() in LINQ)?

  2. Jaco Pretorius says:

    That would be the Inject method. I’ve actually blogged about that before – http://www.jacopretorius.net/2010/08/using-ruby-inject.html

  3. mgreenly says:

    I couldn’t resist but to share a tiny bit more ruby fun. You could write the first line as “list = *1..10″

  4. That’s awesome – I’ve never seen that!

  5. Rico Jones says:

    Just a head’s up: unless I’m mistaken, there’s a typo in your first example. Line 4 should be “i <= 7" to match the console output you have below it. Other than that, thanks for the post.

  6. Well spotted. Corrected. Thanks!