【问题标题】:Ruby random selection from array sometimes returns same value repeatedly从数组中随机选择的 Ruby 有时会重复返回相同的值
【发布时间】:2013-10-15 14:31:24
【问题描述】:

我正在使用它来选择一个随机匹配,我测试它的结果,并绘制一个随机匹配直到它满足while循环的标准:

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

循环10个循环后设置为break(避免无限循环),我会随意跳出循环,查看日志,每次循环都看到Matchup都一样.循环的简化版本是这样的:

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

【问题讨论】:

  • @Davidann 在 PostgreSQL 中是 RANDOM()
  • 不过,在这种情况下,失败的可能性太小,无法在测试中经常看到。相反,我希望涉及查询缓存。可能有一些语法告诉 Postgres 不要使用它。
  • 或者可能是 Active Record 缓存(而不是 Postgres)。
  • @jackerman09 我自己并不真正了解 Rails,但也许是这样:coderwall.com/p/tvybhq

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


【解决方案1】:

添加另一个变体:)

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

除非id 值的集合过多,否则这将很好地工作,在这种情况下,您将洗牌一个非常大的数组。但是,在 1k 到 2k 的集合大小中,用户不会注意到它。

或者简单地说:

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

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

【讨论】:

  • IMO,ids.shuffle.firstids[rand(ids.length)] 清晰得多。:) 给你金星。
  • @Pierre-LouisGottfrois 确实是旧的清洁度/速度权衡:)
  • pluck 是否确保我只会得到一个匹配存在的 ID?
  • @mbratch yes :) 但在这里我们可能想放弃干净的代码,因为它在很大程度上取决于ids 的大小:-/
  • 数据库中可能会有 1k-2k 对决。这会导致您反对您的解决方案吗?
【解决方案2】:

您可以为此使用随机播放:-

Matchup.all.shuffle!.first

【讨论】:

  • 这很简洁,但它确实会获取所有记录来执行此操作。我认为@Davidann 有一个避免获取所有数据的好主意。
  • 谢谢,知道为什么我上面的代码(有时)不起作用?
  • 这很奇怪,我在本地尝试过,随机函数给我随机值:)
  • @NikitaSingh,它对我来说在本地也可以正常工作(我的原始设计在本地工作),但是当部署(在 Heroku 上)时,它就成了一个问题。
【解决方案3】:

假设这个模型是一个普通的 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)])

【讨论】:

  • 这假定数据库中没有丢失的 id。
  • @mcfinnigan:你是对的。我在回答中指出了这一点,然后给出了更好的答案。
  • @mcfinnigan,好点子。数据库中有许多不存在 Matchup 的 ID,因此这不起作用。谢谢!
猜你喜欢
  • 2014-08-09
  • 2021-12-26
  • 1970-01-01
  • 2019-01-28
  • 1970-01-01
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
相关资源
最近更新 更多