变量改变值,红宝石

use*_*058 2 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 origString
  return newString
end
Run Code Online (Sandbox Code Playgroud)

例如,如果我运行 scramble_string("abcd", [3, 1, 2, 0]) origString ,则第一个“puts”中的“abcd”会更改为第二个“dbcd”中的“dbcd”。如果我只声明一次,如何更改 origString 的值?

tad*_*man 5

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

y = "test"
x = y

x[0] = "b"

x
# => "best"
y
# => "best"
Run Code Online (Sandbox Code Playgroud)

你可以这样说:

x.object_id == y.object_id
# => true
Run Code Online (Sandbox Code Playgroud)

它们是相同的物体。你想要的是先制作一个副本:

x = y.dup
x[0] = "b"
x
# => "best"
y
# => "test"
Run Code Online (Sandbox Code Playgroud)

这会产生两个独立的对象:

x.object_id == y.object_id
# => false
Run Code Online (Sandbox Code Playgroud)

因此,在您的情况下,您需要将其更改为:

orig_string = string.dup
Run Code Online (Sandbox Code Playgroud)

话虽这么说,在 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"
Run Code Online (Sandbox Code Playgroud)

请注意,这比带有字符串操作的版本简洁得多。