开发者

What's up with the way ruby alters variables this way?

开发者 https://www.devze.com 2023-01-30 18:35 出处:网络
Sorry about the开发者_开发技巧 vague question.I\'m at a loss for words to describe this phenomenon, thus google wasn\'t much help.Please consider the following code:

Sorry about the开发者_开发技巧 vague question. I'm at a loss for words to describe this phenomenon, thus google wasn't much help. Please consider the following code:

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

This produces:

name age
Jim 36
Jim 36
Jim 36

which is contrary to what I was expecting:

name age
Joe 32
Tom 45
Jim 36

Why is array affected after the fact by modifying a?


You want to set a to a new Array object inside the each. At the moment, you're pushing the same a object to the array, which is why it's returning the same value three times. Even better would be to not use a at all and instead convert the code into something like this:

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

You could make it smaller than that even by moving the line.split to be within the push method, but I think that reduces readability and doesn't explain what information you're getting out of split.


This is slightly more advanced, but to build on Ryan's answer, rather than doing

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

, you could use the map function, and have

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

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

This is a slightly more "functional programming" approach. I'm sure this is a very rough summary, but in functional programming, you don't modify existing objects, you only create new objects instead.

As an aside, if you wanted to verify Ryan's answer, you could use object_id on each of the objects:

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

which gives

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
0

精彩评论

暂无评论...
验证码 换一张
取 消