随机置换迭代器

时间:2013-04-02 10:24:38

标签: ruby ruby-1.9.3

需要使用新的迭代器扩充Enumerable模块,该迭代器以随机顺序返回集合的元素。关于收集的唯一信息 - 它响应每个。没有关于元素的其他假设。 我有一个解决方案 - 将元素包装到Array中,然后使用sample方法:

def each_permuted
    tmp = []
    self.each do |w|
        tmp << w
    end
    tmp.sample(tmp.length).each do |w|
        yield w
    end
end

不喜欢它,因为在这里我们经历了两次收集(甚至三次计算tmp.sample随机排列)。 单身经历是否可能?

2 个答案:

答案 0 :(得分:3)

我怀疑是否可以使用signle。请查看此页面:http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_.22inside-out.22_algorithm

我在文章中实现了名为“由内而外算法”的算法(它经历了两次收集):

def each_permuted
  generator = Random.new
  tmp = []
  self.each do |w|
    r = generator.rand(tmp.size + 1)
    if r == tmp.size
      tmp << w
    else
      tmp << tmp[r]
      tmp[r] = w
    end
  end

  tmp.each do |w|
    yield w
  end
end

试验:

1.9.3p327 :064 > [1,2,3,4,5,6].each_permuted { |x| p x }
1
5
2
6
3
4
 => [1, 5, 2, 6, 3, 4]
1.9.3p327 :065 > [1,2,3,4,5,6].each_permuted { |x| p x }
4
3
2
5
6
1
 => [4, 3, 2, 5, 6, 1]
1.9.3p327 :066 > [1,2,3,4,5,6].each_permuted { |x| p x }
4
5
2
1
3
6
 => [4, 5, 2, 1, 3, 6]

答案 1 :(得分:0)

def each_permuted &pr; shuffle.each(&pr) end
相关问题