在这种情况下,Ruby的地图方法如何工作?

时间:2014-10-05 10:52:46

标签: ruby-on-rails ruby map

当我想在数组中添加doubled值时,我遇到了错误:

arr = [1,2,3]

def my_mistake(arr)
  result = Array.new
  arr.map { |element| result << element * 2 }
end
#=> [[2, 4, 6], [2, 4, 6], [2, 4, 6]]

def solution(arr)
  arr.map { |element| element * 2 }
end
#=> [2,4,6]

然而,回到我的错误以及Ruby中 map 方法的定义。

  

为self的每个元素调用给定的块一次。创建一个包含块返回值的新数组。

我认为 my_mistake 方法必须返回[[2], [2, 4], [2, 4, 6]],但它不会。

每个人都能为我解释这个案子吗?

2 个答案:

答案 0 :(得分:5)

结果数组将包含对同一数组的相同引用的三次出现,因为result是表达式result << element * 2的结果。因此map的结果是(种类)[result, result, result]。这些都指向相同的内容,这是流程结束时result的内容[2, 4, 6]

如果你在每个点克隆数组,你会期望得到什么,这样每个结果元素都会指向不同的数组,并且每次添加都不会影响先前计算的数组:

arr.map { |element| (result << element * 2).clone }
=> [[2], [2, 4], [2, 4, 6]]

答案 1 :(得分:0)

.map返回最后一次计算的表达式,因此不需要结果&lt;&lt;在那里。这对我有用:

def my_mistake(arr)
  result = [] # '= []' is same like '= Array.new', look-up "literal constructors in Ruby"
  new_arr = [] # same like new_arr = Array.new
  until arr.empty?
    new_arr << arr.shift # we add each element of arr, one by one, starting from the beginning
    output << new_arr.map { |e| e * 2} # we calculate *2 for each element
  end
  return result
end
p my_mistake(arr) #=> [[2], [2, 4], [2, 4, 6]]

如果您不确定这是如何工作的,请尝试在第6行之后加上“p output”:

def my_mistake(arr)
  output = []
  new_arr = []
  until arr.empty?
    new_arr << arr.shift
    output << new_arr.map { |e| e * 2}
    p output
  end
  return output
end

my_mistake(arr)

该程序将打印:

[[2]]
[[2], [2, 4]]
[[2], [2, 4], [2, 4, 6]]