Ruby 从列表中随机选取项目,无需迭代

Ruby 从列表中随机选取项目,无需迭代,ruby,Ruby,我在Rails中有以下代码 @related = [] while @related.compact.size < 3 @tag = @car.tag_list.sample #pick a tag from the @car's tag_list @sametags = Car.tagged_with(@tag) # get all cars with that tag @related.push(( @sametags - Array(@car) - @related.co

我在Rails中有以下代码

@related = []
while @related.compact.size < 3
  @tag = @car.tag_list.sample #pick a tag from the @car's tag_list
  @sametags = Car.tagged_with(@tag) # get all cars with that tag
  @related.push(( @sametags - Array(@car) - @related.compact).sample) #put that car in @related
  @counter = @counter + 1 #increment
  break if @counter == 10 #stop if its taking too long
end
@related=[]
而@related.compact.size<3
@tag=@car.tag_list.sample#从@car的tag_列表中选择一个标签
@sametags=Car.taged_with(@tag)#获取所有带有该标签的汽车
@相关.推送(@sametags-Array(@car)-@related.compact.sample)#把那辆车放在@related
@计数器=@计数器+1#增量
如果@counter==10则中断#如果花费的时间太长则停止
结束
我很清楚这段代码效率很低,但我的ruby技能还不能胜任


基本上,我需要做的是用3个带有类似标签的车型随机填充
@related
,这样它们就不会重复了。

您可以使用随机排序来完成此操作

@related = Car.limit(3).order('rand()').tagged_with('blood red')
更新:没有@car

@tag = @car.tag_list.sample
@related = Car.where('id != ?', @car.id).limit(3).order('rand()').tagged_with(@tag)
更新:如果您使用的是acts_as_taggable_on

@related = Car.where('id != ?', @car.id).limit(3).order('rand()')
  .tagged_with(@car.tag_list, any: true)

首先使用“置乱”将阵列洗牌,然后只选择前三项

[1,2,3,4].scramble => [3,1,2,4]
接受一个数字,即样本的大小。因此我认为,您的代码可以简化为:

@tag = @car.tag_list.sample
@sametags = Car.tagged_with(@tag)
@related = (@sametags - [@car]).sample(3)

但这也可能会选择@car itself来尝试我的更新答案。它基本上不包括
@car
。并且还使用了汽车的所有标签列表:)
order('rand()
)`is not cross DB,IIRC。我使用
sample(3)
而不是
order('rand()')
你能发布一个链接到
数组#扰码
方法的文档吗?