从数组中随机选择Ruby有时会重复返回相同的值

时间:2013-10-15 14:31:25

标签: ruby-on-rails ruby arrays loops random

我使用它来选择一个随机的Matchup,并测试它的结果,并绘制一个随机的Matchup,直到它符合while循环的标准:

m = Matchup.order("RANDOM()").first

循环在10个循环后设置为break(以避免无限循环),我会随意中断循环,检查日志,并看每次匹配时匹配是否相同循环。循环的简化版本将是这样的:

counter = 0
while counter < 5
    m = Matchup.order("RANDOM()").first
    logger.debug('Matchup ID: ' + m.id)
    counter += 1
end

日志将如下所示:

Matchup ID: 7
Matchup ID: 7
Matchup ID: 7
Matchup ID: 7
Matchup ID: 7

为什么m = Matchup.order("RANDOM()").first会随意拉不同的比赛?最奇怪的部分是有时候它可以正常工作,而其他一些它被卡在循环b / c m中并没有改变。有什么建议吗?

如果你想看到实际的循环,你可以在这里看到它(在getRandomMatchup函数中):     https://github.com/jackerman09/wdis/blob/master/app/controllers/static_pages_controller.rb

3 个答案:

答案 0 :(得分:2)

添加其他变体:)

ids = Matchup.pluck(:id)
m = Matchup.find( ids.shuffle.first )

除非id值的集合过多,否则这将很有效,在这种情况下,您正在改组非常大的数组。但是,在1k到2k的设置大小中,用户不会注意到它。

或者简单地说:

ids = Matchup.pluck(:id)
m = Matchup.find( ids.sample )

将从ids数组中选择一个随机项。

答案 1 :(得分:1)

假设此模型是正常的ActiveRecord模型,您可以尝试类似:

max_id = Matchup.maximum(:id)
id = rand(max_id)
m = Matchup.find(id)
...

这样做可能比要求数据库为您提供随机排序的记录要便宜。但是,这种方法的缺点是可能会删除记录,因此Matchup.find(id)可能是nil

另一种更好的方法可能是:

ids = Matchup.pluck(:id)
m = Matchup.find(ids[rand(ids.length)])

答案 2 :(得分:1)

你可以使用shuffle: -

Matchup.all.shuffle!.first