each and map


This is a quick 101 on enumeration and ruby blocks, which loosely follows on from my post on basic ruby collections here: Basic Ruby Collections.

Enumerable: can be loosely interpreted as countable. If something is enumerable, it means we can flick through it and do something with the items it hold.

E.g. A deck of cards is enumerable

Enumerable (countable) methods (oversimplifying here) are commonly used to traverse collections and perform some operation on each item. In order to use our enumerable method effectively, we're going to need to know some methods that we can call an the items in our collection.

First, a type to use

We're going to use String, the life-blood of any text-processing application
Lets explore some very basic operations that we can do on strings in ruby.

I've done these commands in an irb console, so feel free to open one up and put in the commands yourself, have a go!

Declare our string variable

 ❯ irb
2.4.1 :001 > name = "Tom Coder"
 => "Tom Coder"

Make all the letters lowercase or uppercase

2.4.1 :002 > name.downcase
 => "tom coder"
2.4.1 :003 > name.upcase
 => "TOM CODER"

Find the length

2.4.1 :005 > name.length
 => 9

Does the string start with a certain character?

2.4.1 :006 > name.start_with?("T")
 => true

Now our collection!

We'll start with an array:

things = ["Tom", "Tim", "Sandy", "Violet"]

We want to do stuff with this array, maybe travel through it and print something out?

each

each is the most basic and commonly used of all the enumerable methods. (This is ruby's for or foreach if you're familiar with other languages.)

things.each do |val|
  puts val
end

Let's try it out on an Array of names.

2.4.1 :002 > things = ["Tom", "Tim", "Sandy", "Violet"]
 => ["Tom", "Tim", "Sandy", "Violet"]

2.4.1 :003 > things.each do |thing|
2.4.1 :004 >   puts(thing.downcase)
2.4.1 :005?> end
tom
tim
sandy
violet
 => ["Tom", "Tim", "Sandy", "Violet"]

There! Translating each name to lowercase in turn and printing the result, not too shabby.

But what if we wanted to do something to those variables along the way, and then keep the result afterwards? The each method won't do that for us. Introducing...

map

Say we wanted to get the uppercase version of all the names!

(Note: The last statement inside a map block is the thing that is put into the resulting array)

2.4.1 :001 > things = ["Tom", "Tim", "Sandy", "Violet"]  
 => ["Tom", "Tim", "Sandy", "Violet"]
2.4.1 :002 > lengths = things.map do |val|
2.4.1 :003 >   val.upcase
2.4.1 :004?> end
 => ["TOM", "TIM", "SANDY", "VIOLET"]