为什么Array#shuffle!不能使用嵌套数组?

时间:2013-02-21 09:03:13

标签: ruby ruby-1.9.3

在这里,我试图了解Array#shuffle!如何使用数组对象。所以我开始在 IRB

中使用它
[1,2,3]
#=> [1, 2, 3]
[1,2,3].shuffle!
#=> [3, 1, 2]

在上面的代码中我理解它是如何工作的。而下面的我试图用更难的方式从各个角落看它。

[1,2,5]
#=> [1, 2, 5]
[1,2,5]<<[1,2,5]
#=> [1, 2, 5, [1, 2, 5]]

直到现在我很好。

[1, 2, 5, [1, 2, 5]].shuffle!
#=> [5, 1, 2, [1, 2, 5]]

上面的代码我有困惑。所以问题低于我的脑袋:

  • (a)为什么shuffle!递归不起作用?正如我所料,内部数组[1, 2, 5]的输出也将被洗牌。但没有发生。

  • (b)为什么shuffle!不会混淆元素数组[1, 2, 5],而只适用于数组1, 2, 5,的{​​{1}}元素?我觉得输出会是[1, 2, 5, [1, 2, 5]]。那么为什么元素数组没有改变它的位置,而只是普通元素只做了?

修改

它表现出非常有趣的行为:

[[1, 2, 5],5, 1, 2]

洗牌是否真的遵循任何订单或随机改组?

5 个答案:

答案 0 :(得分:2)

a)shuffle!改变了数组中对象的顺序,这可以是任何东西的集合,因此该方法不能假设内部的东西也可以或应该被洗牌。

b)我真的不明白这个问题与a)的不同之处。你能解释一下你认为令人困惑的更多内容吗?

答案 1 :(得分:2)

a)为什么shuffle!递归行动?它作用于它传递的对象,在你的例子中是一个包含4个项目的数组 - 它将它们混洗。事实上其中一个是阵列既不在这里也不在那里,其中一个可能是它所关心的驴。

b)它确实对数组元素进行了洗牌,你应该多次尝试过你的小IRB测试,你会发现数组只是没有机会移动。

关于你的编辑问题,你究竟想在这里展示什么,我看不到任何有趣的行为?没有模式,shuffle是伪随机的。

答案 2 :(得分:0)

如果您确实希望递归地对数组进行混洗,则没有问题:

# encoding: utf-8

a = [1,2,3]
a << [6,7,8]

class Array
  alias shuffle_orig shuffle
  def shuffle
    self.shuffle_orig.map { |e| e.respond_to?(:shuffle) ? e.shuffle : e }
  end
end


3.times do
  p a.shuffle
end

结果是:

#⇒ [2, [8, 6, 7], 3, 1]
#⇒ [3, 1, [7, 6, 8], 2]
#⇒ [1, [8, 7, 6], 3, 2]

爆炸版也可能是monckey-patched。

答案 3 :(得分:0)

a=[1,2,4]
#=> [1, 2, 4]
a<<[7,8]

a.each_with_index do |element, index|

  puts "Index: #{index} element: #{element}"
end

使用a<<[7,8]将新对象追加到a数组中。 该对象将具有唯一索引。 Shuffle方法将此索引用于其目的..

Index: 0 element: 1
Index: 1 element: 2
Index: 2 element: 4
Index: 3 element: [7, 8]

附加数组[7,8]被视为1个对象,因此其内部元素不会作为数组a中的元素进行混洗。

答案 4 :(得分:0)

我确信你可以想象一种情况,你需要改变顺序很重要的一组数组的顺序。在这种情况下,shuffle非常方便,如果您的需求发生变化,使用shuffle方法很容易实现递归shuffle。但是,如果Ruby仅包含递归shuffle,则必须编写原始的非递归shuffle方法的逻辑,并且无法使用递归shuffle方法优雅地实现解决方案。我认为大多数语言都喜欢使用简单,通用的方法来处理更复杂的语言。