¿Qué hace el método" map " en Ruby?


Soy nuevo en programación. Puede alguien explicar lo que .map haría en:

params = (0...param_count).map
Author: Danil Speransky, 2012-08-23

6 answers

El método map toma un objeto enumerable y un bloque, y ejecuta el bloque para cada elemento, mostrando cada valor devuelto del bloque (el objeto original no cambia a menos que use map!):

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

Array y Range son tipos enumerables. map con un bloque devuelve un Array. map! muta el array original.

¿Dónde es útil esto, y cuál es la diferencia entre map! y each? He aquí un ejemplo:

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

La salida:

Danil is a programmer
Edmund is a programmer
 401
Author: Danil Speransky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-05 17:42:05

map, junto con select y each es uno de los caballos de batalla de Ruby en mi código.

Le permite ejecutar una operación en cada uno de los objetos de su matriz y devolverlos todos en el mismo lugar. Un ejemplo sería incrementar una matriz de números en uno:

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

Si puede ejecutar un método único en los elementos de su matriz, puede hacerlo en un estilo abreviado como este:

  1. Para hacer esto con el ejemplo anterior, tendrías que hacer algo como esto

    class Numeric
      def plusone
        self + 1
      end
    end
    [1,2,3].map(&:plusone)
    #=> [2,3,4]
    
  2. Para usar más simplemente la técnica de atajo ampersand, usemos un ejemplo diferente:

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

La transformación de datos en Ruby a menudo implica una cascada de operaciones map. Estudio map & select, son algunos de los métodos Ruby más útiles en la biblioteca primaria. Son tan importantes como each.

(map es también un alias para collect. Usa lo que funcione mejor para ti conceptualmente.)

Más útil información:

Si el objeto Enumerable en el que está ejecutando each o map contiene un conjunto de elementos enumerables (hashes, arrays), puede declarar cada uno de esos elementos dentro de sus tuberías de bloque de la siguiente manera:

[["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

En el caso de un Hash (también un objeto Enumerable, un Hash es simplemente una matriz de tuplas con instrucciones especiales para el intérprete). El primer "parámetro pipe" es la clave, el segundo es el valor.

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

Para responder a la pregunta:

Suponiendo que params es un hash, esta sería la mejor manera de mapearlo: Use dos parámetros de bloque en lugar de uno para capturar el par clave y valor para cada tupla interpretada en el hash.

params = {"one" => 1, "two" => 2, "three" => 3}
params.each do |k,v|
  puts "#{k}=#{v}"
end
# one=1
# two=2
# three=3
 58
Author: boulder_ruby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-24 02:38:59

0..param_count significa "hasta e incluyendo param_count". 0...param_count significa "hasta, pero sin incluir param_count".

Range#map no devuelve un Enumerable, en realidad lo asigna a un array. Es lo mismo que Range#to_a.

 4
Author: Pedro Nascimento,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-23 19:15:04

Usando ruby 2.4 puedes hacer lo mismo usando transform_values, esta característica extraída de rails a ruby.

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

h.transform_values { |v| v * 10 }
 #=> {a: 10, b: 20, c: 30}
 4
Author: tokhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-08 16:52:47

"asigna" una función a cada elemento en un Enumerable - en este caso, un rango. Así que llamaría al bloque pasado una vez por cada entero de 0 a param_count (exclusivo - tienes razón sobre los puntos) y devolvería una matriz que contiene cada valor devuelto.

Aquí está la documentación para Enumerable#map. también tiene un alias, collect.

 3
Author: Ry-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-23 03:56:02

Map es una parte del módulo enumerable. Muy similar a "collect" Por Ejemplo:

  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 proporciona valores iterados a través de una matriz que son devueltos por los parámetros de bloque.

 1
Author: gkstr1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-16 21:46:50