这让我抓狂!我一直在尝试编写一个Ruby方法来查找所有排列,以解决Project Euler的问题24.当我交换数组的元素时,它们被正确交换。但是当我尝试在DIFFERENT数组中存储这个交换的数组时,这个新数组只会记住我的交换数组的最新副本!它不会记得旧版本。
当我在循环中打印出来时,它会正确显示所有排列。但是当我打印出烫发(我用它来存储a的所有不同排列)时,它只显示重复几次的1个版本。我该如何解决这个问题?
a = [0, 1, 2, 3]
perms = []
p "a = #{a}" # output: "a = [0, 1, 2, 3]"
perms << a # add a to perms array
p "perms = #{perms}" # output: "perms = [[0, 1, 2, 3]]"
a[0], a[1] = a[1], a[0] # swap 1st 2 elements of a
p "a = #{a}" # output: "a = [1, 0, 2, 3]"
perms << a # add a to perms array
p "perms = #{perms}" # "perms = [[1, 0, 2, 3], [1, 0, 2, 3]]"
a[1], a[2] = a[2], a[1] # swap 2nd 2 elements of a
p "a = #{a}" # "a = [1, 2, 0, 3]"
perms << a # add a to perms array
p "perms = #{perms}" # "perms = [[1, 2, 0, 3], [1, 2, 0, 3], [1, 2, 0, 3]]"
感谢下面的Sawa,“dup”和“clone”方法都解决了我的问题!为什么我原来的方式不起作用?我何时会使用“dup”与“clone”?请给我一些代码示例。
a[0], a[1] = a[1], a[0] # swap 1st 2 elements of a
p "a = #{a}" # output: "a = [1, 0, 2, 3]"
b = a.dup (or a.clone)
perms << b
p "perms = #{perms}" # "perms = [[0, 1, 2, 3], [1, 0, 2, 3]]" *** it remembers!
a[1], a[2] = a[2], a[1] # swap 2nd 2 elements of a
p "a = #{a}" # "a = [1, 2, 0, 3]"
b = a.dup (or a.clone)
perms << b
p "perms = #{perms}" # "perms = [[0, 1, 2, 3], [1, 0, 2, 3], [1, 2, 0, 3]]"
答案 0 :(得分:2)
Ruby中的变量(有一些例外,例如绑定到整数的变量)包含对象的引用,而不是值。以下是运行“irb”的示例:
1.9.3p374 :021 > str1="hi"
=> "hi"
1.9.3p374 :022 > str2=str1
=> "hi"
1.9.3p374 :023 > str1.replace("world")
=> "world"
1.9.3p374 :024 > str2
=> "world"
你会注意到,一旦我替换str1的值,str2的“值”也会改变。那是因为它包含对str1对象的引用。我知道dup和clone之间的一个区别与“freeze”方法有关。如果我调用了str1.freeze,那么它将阻止修改对象str1引用,例如,
1.9.3p374 :055 > str1.freeze
=> "hi"
1.9.3p374 :056 > str1[0]="b"
RuntimeError: can't modify frozen String
from (irb):56:in `[]='
from (irb):56
from /.rvm/rubies/ruby-1.9.3-p374/bin/irb:13:in `<main>
“Dup” - 冻结对象不会创建冻结对象,而克隆则会。
编辑:只是稍微更新....当将右侧的对象分配给左侧的变量(例如,str = Object.new)时,变量接收对象引用。将一个变量分配给另一个变量时,左侧变量会接收右侧变量包含的引用的副本。在任何一种情况下,您仍然在左侧变量中存储对象引用。
答案 1 :(得分:1)
您的原始文件无效,因为您一直在修改相同的数组实例a
。
每次将dup
原始数组修改为不同的数组。或者,通过不依赖破坏性方法创建Array
的新实例。
a = original_array
b = a.dup
... # do some modifications to `b`
perms << b
c = a.dup
... # do some modifications to `c`
perms << c
...
答案 2 :(得分:0)
如果您不喜欢重新发明轮子,可以使用facet gem。
gem install facets
require 'facets'
[1, 2, 3].permutation
#=> [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]