ruby以这种方式改变变量的方式是什么?

时间:2010-12-12 21:53:15

标签: ruby

对这个模糊的问题感到抱歉。我无法用言语来描述这种现象,因此谷歌没有多大帮助。请考虑以下代码:

array = [["name", "age"]]
a = []

x = ["Joe 32",
     "Tom 45",
     "Jim 36"]

x.each do |line|
  name, age = line.split(/\s/)
  a[0] = name
  a[1] = age

  array.push(a)
end  

array.each do |x|
  puts x.join(" ")
end

这会产生:

name age
Jim 36
Jim 36
Jim 36

这与我的期望相反:

name age
Joe 32
Tom 45
Jim 36

通过修改array

,为什么a会在事后受到影响

2 个答案:

答案 0 :(得分:5)

您想将a设置为Array内的新each对象。目前,您正在将相同的 a对象推送到数组,这就是它返回相同值三次的原因。更好的方法是根本不使用a,而是将代码转换为如下代码:

x.each do |line|
  name, age = line.split(/\s/)
  array.push([name, age])
end

即使将line.split移到push方法内,您也可以将其缩小,但我认为这会降低可读性,并且无法解释您从split获取的信息{1}}。

答案 1 :(得分:0)

这稍微高级一些,但要以Ryan的答案为基础,而不是

x.each do |line|
  name, age = line.split(/\s/)
  array.push([name, age])
end

,您可以使用map功能,并拥有

people = x.map do |line|
  name, age = line.split(/\s/)
  [name, age]
end

desired_result = [["name", "age"]] + people

这是一种稍微“功能性编程”的方法。我确信这是一个非常粗略的总结,但在函数式编程中,您不修改现有对象,而只是创建新对象。

顺便说一句,如果您想验证Ryan的答案,可以在每个对象上使用object_id

array.each_with_index do |object, index|
  puts "Object #{index} (which is #{object.inspect}) has an object id of #{object.object_id}"
end

给出了

Object 0 (which is ["name", "age"]) has an object id of 10204144
Object 1 (which is ["Jim", "36"]) has an object id of 10248384
Object 2 (which is ["Jim", "36"]) has an object id of 10248384
Object 3 (which is ["Jim", "36"]) has an object id of 10248384