变量改变值,ruby

变量改变值,ruby,ruby,Ruby,我不确定这个名为origString的变量是如何改变循环中的值的 def scramble_string(string, positions) i = 0 origString = string puts origString newString = string while i < string.length newString[i] = origString[positions[i]] i = i + 1 end puts origStrin

我不确定这个名为origString的变量是如何改变循环中的值的

def scramble_string(string, positions)
  i = 0
  origString = string
  puts origString
  newString = string
  while i < string.length
    newString[i] = origString[positions[i]]
    i = i + 1
  end
  puts origString
  return newString
end
例如,如果我运行scramble\u stringabcd,[3,1,2,0] 原始字符串从第一个puts中的abcd更改为第二个puts中的dbcd。 如果我只声明一次origString的值,我该如何更改它呢?

当你在Ruby中说x=y时,它创建了一个引用完全相同对象的变量。对x的任何修改将适用于y,反之亦然:

y = "test"
x = y

x[0] = "b"

x
# => "best"
y
# => "best"
因此,您可以看出:

x.object_id == y.object_id
# => true
它们是相同的物体。您需要的是先复制一份:

x = y.dup
x[0] = "b"
x
# => "best"
y
# => "test"
这将产生两个独立的对象:

x.object_id == y.object_id
# => false
因此,在您的情况下,您需要的是将其更改为:

orig_string = string.dup
话虽如此,在Ruby中处理事情的最佳方法通常是使用返回副本的函数,而不是就地操作。更好的解决方案是:

def scramble_string(string, positions)
  (0...string.length).map do |p|
    string[positions[p]]
  end.join
end

scramble_string("abcd", [3, 1, 2, 0])
"dbca"

请注意,这比使用字符串操作的版本要简洁得多。

Ruby强烈建议使用orig_string之类的名称,不使用大写字母,因为case在Ruby中具有重要意义。变量不会更改其值。值正在更改其内容,因为您在第7行告诉它。@JörgWMittag您能详细说明一下吗?“它是如何工作的”值正在改变它的内容。@Dharshan:如果一个对象支持改变它的状态,你可以通过发送一条消息告诉它改变它的状态来改变它的状态。例如,您可以通过发送[]=消息或upcase!来更改字符串的状态!消息。@JörgWMittag基于tadman的回答,当我们说x=y时,两个对象ID都是相同的,如果我们改变x='pest'的整个值,对象ID将完全改变。如果我们在更改值之前进行检查,则x[0]和y[0]的对象_ID不同。但是更改xi,ex[0]中的单个值反映了原始字符串y,HOW?或字符串.chars.values_的*位置。join@tadman你的陈述需要解释一下。当我们说x=y时,两个对象的id是相同的,但是x[0]和y[0]的对象id是不同的。如果我们改变x的整个值,='pest'对象的id将完全改变。但是改变x中的一个值会反映原始字符串y,如何?需要了解更多关于此的信息。x[0]返回单个字符的子字符串。因为每个子字符串操作都可以生成新的、唯一的字符串,甚至x[0]。对象\u id==x[0]。对象\u id通常不是真的。在设计中,只有少数东西是与对象id等效的:符号、零、真、假和一些数字。