Categories
Uncategorized

Enumerating Ruby’s “Enumerable” Module, Part 2: “collect”, a.k.a. “map”

Ruby gemstoneHere’s part 2 of my ongoing series covering the methods in Ruby’s Enumerable module — this one covers the collect method, a.k.a. map.

Read on…

In the last article in this series covering the methods in Ruby’s Enumerable module, I covered all? and any?. In this installment, I’ll look at the collect method, a.k.a. the map method.

collect, a.k.a. map

  • In plain language: Create an array by performing some operation on every item in the given collection.
  • Ruby.Doc.org’s entry: Enumerable#collect / Enumerable#map
  • Expects: A block containing the operation (it’s optional, but you’re likely to use one most of the time).
  • Returns: An array made up of items created by performing some operation on the given collection.

collect and map are synonyms — you can use either. I personally prefer map as it’s shorter and makes more sense: I view the operation as using a function to map a collection to an array.

Using collect/map with Arrays

When used on an array and a block is provided, collect/map passes each item to the block, where the operation in the block is performed on the item and the result is then added to the result array. Note the the result array has the same number of elements as the given array.

[1, 2, 3, 4].map {|number| number ** 2}
=> [1, 4, 9, 16]

["Aqua", "Bat", "Super", "Wonder Wo"].map {|adjective| adjective + "man"}
=> ["Aquaman", "Batman", "Superman", "Wonder Woman"]

When the block is omitted, collect/map uses this implied block: {|item| item}, which means when applied on an array without a block, collect/map is the identity function — the resulting array is the same as the given array.

[1, 2, 3, 4].map
=> [1, 2, 3, 4]

["Aqua", "Bat", "Super", "Wonder Wo"].map
=> ["Aqua", "Bat", "Super", "Wonder Wo"]

Using collect/map with Hashes

When used on a hash and a block is provided, collect/map passes each key/value pair in the hash to the block, which you can “catch” as either:

  1. A two-element array, with the key as element 0 and its corresponding value as element 1, or
  2. Two separate items, with the key as the first item and its corresponding value as the second item.

Each key/value pair is passed to the block, where the operation in the block is performed on the item and the result is then added to the result array. Note the the result array has the same number of elements as the given array.

burgers = {"Big Mac" => 300, "Whopper with cheese" => 450, "Wendy's Double with cheese" => 320}

# What if I had just half a burger?
burgers.map {|burger| burger[1] / 2}
=> [160, 150, 225]

burgers.map {|sandwich, calories| calories / 2}
=> [160, 150, 225]

burgers.map {|burger| "Have a tasty #{burger[0]}!"}
=> ["Have a tasty Wendy's Double with cheese!", "Have a tasty Big Mac!", "Have a tasty Whopper with cheese!"]

burgers.map {|sandwich, calories| "Have a tasty #{sandwich}!"}
=> ["Have a tasty Wendy's Double with cheese!", "Have a tasty Big Mac!", "Have a tasty Whopper with cheese!"]

burgers.map {|sandwich, calories| ["Half a #{sandwich}", calories / 2]}
=> [["Half a Wendy's Double with cheese", 160], ["Half a Big Mac", 150], ["Half a Whopper with cheese", 225]]

When the block is omitted, collect/map uses this implied block: {|item| item}, which means when applied on an hash without a block, collect/map returns an array containing a set of two-item arrays, one for each key/value pair in the hash. For each two-item array, item 0 is the key and item 1 is the corresponding value.

burgers = {"Big Mac" => 300, "Whopper with cheese" => 450, "Wendy's Double with cheese" => 320}

burgers.map
=> [["Wendy's Double with cheese", 320], ["Big Mac", 300], ["Whopper with cheese", 450]]

Special Case: Using collect/map on Empty Arrays and Hashes

When applied to an empty array or hash, with or without a block, all? always returns true.

[].map
=> []

[].map {|item| item * 2}
=> []

{}.map
=> []

{}.map {|sandwich, calories| "Have a tasty #{sandwich}!"}
=> []

In the Next Installment…

…the detect (a.k.a. find) method.

One reply on “Enumerating Ruby’s “Enumerable” Module, Part 2: “collect”, a.k.a. “map””

Great series! Just a note on a type, probably a carryover from the first post:

You have:
Special Case: Using collect/map on Empty Arrays and Hashes
When applied to an empty array or hash, with or without a block, all? always returns true.

I think you mean to say:
Special Case: Using collect/map on Empty Arrays and Hashes
When applied to an empty array or hash, with or without a block, map always returns an empty array.

Comments are closed.