我有两个清单:
@content_old = Content.where("state = ?", "old").order('ctr DESC')
@content_new = Content.where("state = ?", "new").order('RAND()')
我想合并这些列表,但第二个列表最后添加到第一个列表。我想"随机合并",即第二个列表的每个元素与RANDOM位置的第一个列表合并
第一个集合中的项目应该保留其相对顺序。
答案 0 :(得分:3)
为什么不做一个查询
Content.where(state: ['old','new']).order('RAND()')
你想要以任意方式随机排序,所以为什么要排序和排序然后排序'
<小时/> 好的,根据新信息我的第二个想法,诀窍是用随机ctr填充第二个列表,然后进行一次排序而不用担心合并
content_old = Content.where(state: 'old')
content_new = Content.select('*, RAND() as ctr').where(state: 'new')
@random_content = (content_old+content_new).sort_by(&:ctr).reverse
如果您不真正需要ctr值,这将有效,因为它会将随机值添加到内存中的某些记录中,如果您想要格外谨慎,可以在数据库中安全像这样打readonly
:
content_new = Content.readonly.select('*, RAND() as ctr').where(state: 'new')
要自定义RAND()
您可以阅读doc page的范围,它可以显示如何设置RAND()
的开始和结束
答案 1 :(得分:1)
对于大型数组可能效率不高,但您可以将“new”数组中的每个项目随机插入(已排序)“旧”数组中。类似的东西:
sorted = Content.where(state: 'old').order('ctr DESC').to_a
others = Content.where(state: 'new')
others.each { |item| sorted.insert(rand(0..sorted.size), item) }
以下是实际数据的示例:
10.times do
sorted = (1..10).to_a
others = %i(foo bar baz)
others.each { |item| sorted.insert(rand(0..sorted.size), item) }
p sorted
end
输出:
[:bar, 1, 2, 3, 4, 5, 6, 7, :foo, 8, 9, 10, :baz]
[1, 2, :bar, 3, 4, :baz, 5, 6, 7, 8, 9, 10, :foo]
[1, 2, 3, 4, 5, 6, :foo, :bar, 7, 8, 9, :baz, 10]
[1, 2, 3, 4, 5, 6, :foo, :bar, 7, 8, :baz, 9, 10]
[1, 2, 3, 4, :foo, 5, :baz, 6, 7, :bar, 8, 9, 10]
[1, :baz, 2, 3, 4, 5, :foo, 6, 7, 8, :bar, 9, 10]
[:foo, 1, 2, 3, 4, 5, :bar, :baz, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, :baz, :bar, 8, 9, :foo, 10]
[1, 2, 3, 4, 5, 6, :bar, :foo, :baz, 7, 8, 9, 10]
[1, 2, 3, 4, 5, :bar, 6, :foo, 7, 8, 9, 10, :baz]