合并两个列表,Ruby on Rails

时间:2015-02-02 14:35:03

标签: ruby-on-rails ruby

我有两个清单:

@content_old = Content.where("state = ?", "old").order('ctr DESC')
@content_new = Content.where("state = ?", "new").order('RAND()')

我想合并这些列表,但第二个列表最后添加到第一个列表。我想"随机合并",即第二个列表的每个元素与RANDOM位置的第一个列表合并

第一个集合中的项目应该保留其相对顺序。

2 个答案:

答案 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]