By bigpotato


2012-08-23 03:54:25 8 Comments

I'm new to programming. Can someone explain what .map would do in:

params = (0...param_count).map

6 comments

@tokhi 2016-12-08 16:52:47

Using ruby 2.4 you can do the same thing using transform_values, this feature extracted from rails to ruby.

h = {a: 1, b: 2, c: 3}

h.transform_values { |v| v * 10 }
 #=> {a: 10, b: 20, c: 30}

@boulder_ruby 2013-10-11 16:56:05

map, along with select and each is one of Ruby's workhorses in my code.

It allows you to run an operation on each of your array's objects and return them all in the same place. An example would be to increment an array of numbers by one:

[1,2,3].map {|x| x + 1 }
#=> [2,3,4]

If you can run a single method on your array's elements you can do it in a shorthand-style like so:

  1. To do this with the above example you'd have to do something like this

    class Numeric
      def plusone
        self + 1
      end
    end
    [1,2,3].map(&:plusone)
    #=> [2,3,4]
    
  2. To more simply use the ampersand shortcut technique, let's use a different example:

    ["vanessa", "david", "thomas"].map(&:upcase)
    #=> ["VANESSA", "DAVID", "THOMAS"]
    

Transforming data in Ruby often involves a cascade of map operations. Study map & select, they are some of the most useful Ruby methods in the primary library. They're just as important as each.

(map is also an alias for collect. Use whatever works best for you conceptually.)

More helpful information:

If the Enumerable object you're running each or map on contains a set of Enumerable elements (hashes, arrays), you can declare each of those elements inside your block pipes like so:

[["audi", "black", 2008], ["bmw", "red", 2014]].each do |make, color, year|
  puts "make: #{make}, color: #{color}, year: #{year}"
end
# Output:
# make: audi, color: black, year: 2008
# make: bmw, color: red, year: 2014

In the case of a Hash (also an Enumerable object, a Hash is simply an array of tuples with special instructions for the interpreter). The first "pipe parameter" is the key, the second is the value.

{:make => "audi", :color => "black", :year => 2008}.each do |k,v|
    puts "#{k} is #{v}"
end
#make is audi
#color is black
#year is 2008

To answer the actual question:

Assuming that params is a hash, this would be the best way to map through it: Use two block parameters instead of one to capture the key & value pair for each interpreted tuple in the hash.

params = {"one" => 1, "two" => 2, "three" => 3}
params.each do |k,v|
  puts "#{k}=#{v}"
end
# one=1
# two=2
# three=3

@tjmcewan 2014-06-26 01:52:52

This doesn't work for me in irb. I get NoMethodError: private method 'plusone' called for 1:Fixnum in ruby 2 and 'wrong number of args' in ruby 1.9/1.8. Anyway, I used a lambda: plusone = ->(x) { x + 1 } then take out the symbol specifier: [1,2,3].map(&plusone).

@boulder_ruby 2014-06-26 03:05:49

hmm sounds like you declared private inside of the class where you put your method before you put your method

@tjmcewan 2014-06-27 03:34:07

Yeah, it totally does. Except it wasn't. :( First of all it was in a straight script w/o classes, secondly in plain irb. Here's my copy/paste of your code: gist.github.com/tjmcewan/a7e4feb2976a93a5eef9

@boulder_ruby 2014-06-27 15:50:11

Yeah, I totally just put a bad example in my code I'm sorry. Try the modified code. It works now...

@tekknolagi 2014-07-01 00:32:56

@boulder_ruby is there a way to do this with a normal method — as in, not a class method?

@boulder_ruby 2016-01-26 02:23:52

@tekknolagi none of the code above uses class methods. Class methods are declared inside a class by this code def self.methodnam. What I've done above is to create instance methods via def methodnam.

@tekknolagi 2016-01-26 06:38:12

@boulder_ruby It's been quite some time since I asked that question, but I believe I meant "Can one map over an Enumerable with a method outside of a class?" But it doesn't matter much any more :)

@gkstr1 2016-09-16 21:46:50

Map is a part of the enumerable module. Very similar to "collect" For Example:

  Class Car

    attr_accessor :name, :model, :year

    Def initialize (make, model, year)
      @make, @model, @year = make, model, year
    end

  end

  list = []
  list << Car.new("Honda", "Accord", 2016)
  list << Car.new("Toyota", "Camry", 2015)
  list << Car.new("Nissan", "Altima", 2014)

  p list.map {|p| p.model}

Map provides values iterating through an array that are returned by the block parameters.

@BKSpurgeon 2016-09-20 23:30:26

map is exactly the same as collect.

@Pedro Nascimento 2012-08-23 03:57:04

0..param_count means "up to and including param_count". 0...param_count means "up to, but not including param_count".

Range#map does not return an Enumerable, it actually maps it to an array. It's the same as Range#to_a.

@Danil Speransky 2012-08-23 04:01:29

The map method takes an enumerable object and a block, and runs the block for each element, outputting each returned value from the block (the original object is unchanged unless you use map!):

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

Array and Range are enumerable types. map with a block returns an Array. map! mutates the original array.

Where is this helpful, and what is the difference between map! and each? Here is an example:

names = ['danil', 'edmund']

# here we map one array to another, convert each element by some rule
names.map! {|name| name.capitalize } # now names contains ['Danil', 'Edmund']

names.each { |name| puts name + ' is a programmer' } # here we just do something with each element

The output:

Danil is a programmer
Edmund is a programmer

@bigpotato 2012-08-23 04:06:10

thanks speransky for the example. then how is .map different from .each?

@bigpotato 2012-08-23 04:18:45

Ahhh I get it. So .map actually mutates the array while .each just loops through the array to access the values while leaving the original array untouched?

@lifecoder 2013-04-29 07:26:59

I don't think so. each and map works the same way, but while each is an iterator only, map has map! form, which mutates an object given. Also map has a collect synonym with no differences.

@lifecoder 2013-04-30 09:57:24

@SperanskyDanil, it is about @Edmund's comment, which you could see right above mine, for this part: "So .map actually mutates the array while .each just loops". #map actually doesn't mutate anything, #map! does.

@kaleidic 2013-08-12 14:56:20

It is hazardous for casual readers that the opening sentence describes map as though it were map!

@Michael Durrant 2013-11-05 17:42:44

wasn't wrong, could just be a little more explicit. Updated Q

@davej 2013-11-27 19:50:51

to see the difference between map and each, open an IRB window and look at the results for y and z in the following code: y = [1,2,3].each {|x| x + 1}; z = [1,2,3].map {|x| x + 1}

@inquisitive 2014-12-02 05:28:01

@davej: Whoa, I got different answers from both of them, but I didn't understand why is this so?

@davej 2014-12-13 16:52:50

@Inquisitive: 'each' returns the array that calls it (in the example, [1,2,3]) when a block is supplied, 'map' returns a new array populated with the values calculated by the block. This might help: set the variable ary = [1,2,3], and check out it's object_id. Then run y = ary.each {|x| x + 1}; z = ary.map {|x| x + 1}. Now check the object_id's of y and z. y has the same object_id as ary (because each returned ary), but z has a different object_id, because map returned a new array.

@Ry- 2012-08-23 03:56:02

It "maps" a function to each item in an Enumerable - in this case, a range. So it would call the block passed once for every integer from 0 to param_count (exclusive - you're right about the dots) and return an array containing each return value.

Here's the documentation for Enumerable#map. It also has an alias, collect.

@Pedro Nascimento 2012-08-23 03:58:18

It's weird, but Range#map actually converts it to an array.

@Ry- 2012-08-23 03:58:39

@PedroNascimento: Yeah... that's what I said?

@Pedro Nascimento 2012-08-23 04:02:35

Sorry, I wasn't aware that map called by itself didn't return an Enumerable, like each. I thought it did.

Related Questions

Sponsored Content

20 Answered Questions

[SOLVED] How to call shell commands from Ruby

  • 2008-08-05 12:56:52
  • CodingWithoutComments
  • 513535 View
  • 1036 Score
  • 20 Answer
  • Tags:   ruby shell interop

10 Answered Questions

[SOLVED] How to convert a string to lower or upper case in Ruby

8 Answered Questions

[SOLVED] How to map and remove nil values in Ruby

  • 2012-11-21 02:29:13
  • Pete Hamilton
  • 220735 View
  • 341 Score
  • 8 Answer
  • Tags:   ruby

24 Answered Questions

[SOLVED] How to write a switch statement in Ruby

19 Answered Questions

[SOLVED] What is attr_accessor in Ruby?

  • 2010-12-06 21:07:06
  • dennismonsewicz
  • 452563 View
  • 1002 Score
  • 19 Answer
  • Tags:   ruby

25 Answered Questions

[SOLVED] Check if a value exists in an array in Ruby

  • 2009-12-31 17:49:03
  • user211662
  • 828954 View
  • 1272 Score
  • 25 Answer
  • Tags:   ruby arrays

15 Answered Questions

[SOLVED] What does map(&:name) mean in Ruby?

5 Answered Questions

[SOLVED] Difference between map and collect in Ruby?

8 Answered Questions

[SOLVED] What does %w(array) mean?

14 Answered Questions

[SOLVED] A concise explanation of nil v. empty v. blank in Ruby on Rails

  • 2009-05-19 22:51:36
  • Arrel
  • 301737 View
  • 1105 Score
  • 14 Answer
  • Tags:   ruby-on-rails ruby

Sponsored Content