我有一个由多个Class对象组成的数组,按shuffle排序:
@streams = (Product.all + List.all + Post.all).shuffle
在供稿页面(如Facebook上的时间轴页面)中,对象的内容用.each显示,并且在每个Class上,都应用了特定的部分:
@streams.each do |stream|
<% if stream.is_a?(Product) %>
<%= render 'product_partial', object: stream %>
<% elsif stream.is_a?(List) %>
<%= render 'list_partial', object: stream %>
<% end %>
<% end %>
目标:因为应用程序中有很多产品(例如:200个),而帖子(100个)更少,列表(10个)更少,所以我想对每个内容(类)下达命令。这样,帖子和列表就不会淹没在产品上。
在一句话中:对于20种产品,显示2个帖子,1个列表。
有什么想法吗? 非常感谢。
答案 0 :(得分:3)
我将使用概率和本机红宝石枚举器:
@streams =
[Product, List, Post].map(&:all).map(&:shuffle)
type =
case rand 23
when 0..19 then 0
when 20..21 then 1
else 2
end
@streams[type].pop # pop one element from the respective array
这有一个缺点,一种类型可能先于其他类型而结束,并且您可能需要显式检查并使用 still nothausted 类型,但它似乎比显式的1-per更好。 -2-per-20,因为它在某种程度上仍具有伪随机顺序。
答案 1 :(得分:2)
您可以执行以下操作:
@streams = custom_order(Products.all, Lists.all, Posts.all)
def custom_order(products, lists, posts)
products_blocks = products.in_groups_of(20, false)
lists_blocks = lists.in_groups_of(2, false)
posts_blocks = posts.in_groups_of(1, false)
result = []
biggest_array = [products_blocks.length, lists_blocks.length, posts_blocks.length].max
1.upto(biggest_array) do |_|
# here we're pushing the blocks, result will be something like [[product, product .. product] [list, list] [posts]]
result << products_blocks.shift
result << lists_blocks.shift
result << posts_blocks.shift
# is ok if one of the blocks is nil, we'll use compact later
end
# result => [[product product product] [list list] [post] [product product] [list] nil]
# compact to remove the nils
# result => [[product product product] [list list] [post] [product product] [list]]
# after flatten
# result => [product product product list list post product product list]
result.compact.flatten
end
编辑:更改了紧凑和扁平化