交叉实现确定性数组#shuffle [英] Cross-Implementation Deterministic Array#shuffle

查看:64
本文介绍了交叉实现确定性数组#shuffle的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以将随机数生成器传递给Array#shuffle,从而使随机播放具有确定性.

It is possible to pass a random number generator to Array#shuffle that makes the shuffle deterministic.

例如,在MRI 1.9.3p327中:

For example, in MRI 1.9.3p327:

[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 2, 4, 3]
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 2, 4, 3]

但是,未指定Random的随机数生成器实现.因此,Ruby的其他实现会有不同的结果.

However, the random number generator implementation of Random isn't specified. Because of this, other implementations of Ruby have different results.

在Rubinius 2.0.0rc1(1.9.3版本2012-11-02 JI)中:

In Rubinius 2.0.0rc1 (1.9.3 release 2012-11-02 JI):

[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 3, 2, 4]
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 3, 2, 4]

顺便说一句,jruby-1.7.1使用与MRI 1.9.3p327相同的随机数生成器,但这只是偶然,不能保证.

Incidentally, jruby-1.7.1 uses the same random number generator as MRI 1.9.3p327, but this is just by chance, not guaranteed.

为了具有一致的跨实现确定性改组,我想将自定义随机数生成器传递给Array#shuffle.我以为这样做很简单,但事实证明它很复杂.

In order to have consistent-across-implementation deterministic shuffle, I would like to pass a custom random number generator into Array#shuffle. I thought this would be trivial to do, but it turns out to be quite complicated.

这是我首先在MRI中尝试过的方法:

Here is what I tried first, in MRI:

class NotRandom; end
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [4, 3, 2, 1]
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [4, 2, 1, 3]

我希望有一个NoMethodError告诉我我需要实现的接口.

I expected a NoMethodError telling me the interface I needed to implement.

有什么见解吗?

更新:

正如@glebm指出的那样,NotRandom继承了Kernel#rand,这是所需的接口.这很容易解决,但不幸的是没有提供解决方案.

As @glebm points out, NotRandom inherited Kernel#rand, which is the interface needed. This is easily worked around, but unfortunately does not offer a solution.

class NotRandom
  def rand(*args)
    0
  end
end

在RBX中:

[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [1, 2, 3, 4]

在MRI中:

[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [2, 3, 4, 1]

推荐答案

对我来说,解决方案是两件事的结合:

For me, the solution was a combination of two things:

  1. 找出随机API.只是rand.

实施我自己的改组,因为不同的Ruby实现不一致.

Implement my own shuffle, because different Ruby implementations aren't consistent.

我使用了my_array.sort_by { @random_generator.rand }.

这篇关于交叉实现确定性数组#shuffle的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆