map and each

It is a bit difficult for me to understand the difference between map and each, until I found out this in irb accidentally,

irb(main):001:0> name = %w{guido knuth adrian dhh pg}
=> ["guido", "knuth", "adrian", "dhh", "pg"]
irb(main):002:0> name.each {|n| n.upcase}
=> ["guido", "knuth", "adrian", "dhh", "pg"]
irb(main):003:0> name.map {|n| n.upcase}
=> ["GUIDO", "KNUTH", "ADRIAN", "DHH", "PG"]

map and each are suppose to do almost the same thing, but why each didn’t return the correct result in uppercase like what map did?

The different is each yield each element in the collection to the code block, in this case perform the upcase method, but return the receiver, which is the original array, hence an array of lower case names.

Whereas, map return a new array, consists of elements already went through the code block, hence an array of upper case names.

irb(main):007:0> name.each {|n| p n.upcase}
"GUIDO"
"KNUTH"
"ADRIAN"
"DHH"
"PG"
=> ["guido", "knuth", "adrian", "dhh", "pg"]
irb(main):006:0> name.map {|n| p n.upcase}
"GUIDO"
"KNUTH"
"ADRIAN"
"DHH"
"PG"
=> [nil, nil, nil, nil, nil]

So here you can see with p, both map and each output the uppercase names, but look more carefully, the return value of each, as expected, is the original array. map however, return an array of nils!

Why is that?

7 Responses to “map and each”

  1. Anton says:

    Because, “each” does not change the object to be used.
    But the “map” changes. Since the method of “p” always returns nil, name.map (| n | p n.upcase) return [nil, nil, nil, nil, nil]

  2. kahfei says:

    Hi Anton, thanks, silly me, of course p always return nil,

    irb(main):006:0> p 2+1
    3
    => nil

    Now, I get the nils array for map part. But why p didn’t return the nil array for each? Is it because of the binding to each, which return the receiver is stronger then the binding to p, which should return nil?

  3. Anton says:

    Hi!
    Sorry, i don`t understand your question.
    Why name.map {|n| p n.upcase} return array of nils?
    Because map change every element in the array to the value given in the block.
    P.S. Sorry for my bad english, i from Russia :)

  4. kahfei says:

    Hi Anton,

    No problem, English is not my mother tongue as well, :-)
    Actually my question is why “p” return nil for “map” but not for “each”.

    Then, I read again your comment, now I can see why.

    “map” return a new array consist of elements processed by the code block, hence all the “nils” from “p”.
    “each” return the receiver of the code block, which is always the original array, ["guido", "knuth", "adrian", "dhh", "pg"].

    Hey, thanks again, Anton.

  5. Anton says:

    Yes!
    No problem, let me know if you have questions :)

  6. Deswing666 says:

    it was very interesting to read http://www.kahfei.com
    I want to quote your post in my blog. It can?
    And you et an account on Twitter?

  7. kahfei says:

    Deswing, sure, if my post did bring any help in anyway, you are free to quote it :-) .

Leave a Reply