Ruby中的"map"方法做了什么?

big*_*ato 243 ruby enumeration map range

我是编程新手.有人可以解释一下.map会做什么:

params = (0...param_count).map
Run Code Online (Sandbox Code Playgroud)

Dan*_*sky 423

map方法采用可枚举对象和块,并为每个元素运行块,从块输出每个返回值(原始对象不变,除非您使用map!):

[1, 2, 3].map { |n| n * n } #=> [1, 4, 9]
Run Code Online (Sandbox Code Playgroud)

Array并且Range是可枚举的类型.map使用块返回一个数组. map!改变原始数组.

这有什么用,有什么区别map!each?这是一个例子:

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
Run Code Online (Sandbox Code Playgroud)

输出:

Danil is a programmer
Edmund is a programmer
Run Code Online (Sandbox Code Playgroud)

  • 对于休闲读者而言,开头的句子描述"地图"就好像它是"地图!"一样危险 (24认同)
  • 要查看map和each之间的区别,打开IRB窗口并查看以下代码中y和z的结果:y = [1,2,3] .each {| x | x + 1}; z = [1,2,3] .map {| x | x + 1} (12认同)
  • @Inquisitive:'each'返回调用它的数组(在示例中为[1,2,3]),当提供一个块时,'map'返回一个填充了块计算值的新数组.这可能会有所帮助:设置变量ary = [1,2,3],并检查它的object_id.然后运行y = ary.each {| x | x + 1}; z = ary.map {| x | x + 1}.现在检查y和z的object_id.y与ary具有相同的object_id(因为每个返回ary),但z具有不同的object_id,因为map返回了一个新数组. (7认同)
  • 谢谢speransky的例子。那么.map与.each有何不同? (2认同)
  • 啊,我明白了。因此,.map实际上会改变数组,而.each只是循环遍历该数组以访问值,同时保持原始数组不变? (2认同)

bou*_*uby 65

map,selecteach我的代码中的Ruby是其中一个主力.

它允许您对每个数组的对象运行操作,并将它们全部返回到同一位置.一个例子是将数字数组增加一:

[1,2,3].map {|x| x + 1 }
#=> [2,3,4]
Run Code Online (Sandbox Code Playgroud)

如果你可以在数组的元素上运行单个方法,你可以像这样的速记样式:

  1. 要使用上面的示例执行此操作,您必须执行以下操作

    class Numeric
      def plusone
        self + 1
      end
    end
    [1,2,3].map(&:plusone)
    #=> [2,3,4]
    
    Run Code Online (Sandbox Code Playgroud)
  2. 为了更简单地使用&符号快捷方式技巧,让我们使用另一个例子:

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

在Ruby中转换数据通常涉及一系列map操作.研究map&select,它们是主库中最有用的Ruby方法.他们和他们一样重要each.

(map也是别名collect.在概念上使用最适合你的东西.)

更多有用的信息:

如果您正在运行或运行的Enumerable对象包含一组Enumerable元素(哈希,数组),您可以在块管道中声明每个元素,如下所示:eachmap

[["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
Run Code Online (Sandbox Code Playgroud)

对于Hash(也是一个Enumerable对象,Hash只是一个元组数组,带有解释器的特殊指令).第一个"管道参数"是键,第二个是值.

{:make => "audi", :color => "black", :year => 2008}.each do |k,v|
    puts "#{k} is #{v}"
end
#make is audi
#color is black
#year is 2008
Run Code Online (Sandbox Code Playgroud)

回答实际问题:

假设这params是一个散列,这将是映射它的最佳方式:使用两个块参数而不是一个来捕获散列中每个解释元组的键和值对.

params = {"one" => 1, "two" => 2, "three" => 3}
params.each do |k,v|
  puts "#{k}=#{v}"
end
# one=1
# two=2
# three=3
Run Code Online (Sandbox Code Playgroud)


Ric*_*etz 13

对于任何需要可视化它的人:

直观地解释地图方法示例

地图什么都不做

地图的作用甚至更少

地图一声巨响!

完整的故事如下:

https://richstone.io/rubys-map-collect-methods-explained-visually/


tok*_*khi 6

使用ruby 2.4你可以使用相同的东西transform_values,这个功能从rails提取到ruby.

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

h.transform_values { |v| v * 10 }
 #=> {a: 10, b: 20, c: 30}
Run Code Online (Sandbox Code Playgroud)