我必须在没有降低性能的情况下解决问题。
我正在整合我的编辑CMS a"赞助"内容系统。赞助内容是有些日子在我的主页上获得随机位置的内容。
我有我的内容课,有些内容有一个标志"赞助"。
在我的HomeController中,我调用了Cover的内容。
@content = Content.for_cover
结果是一个包含20个对象的数组,其中一些对象是赞助的。
内容按默认范围(publication_date DESC)排序,所以在我的主页上,它们是从最新到最旧的订购,但我需要赞助内容"覆盖"默认范围并采取随机位置。
我试图找到最佳解决方案:我不想通过大量查询来降低主页渲染的性能。
有什么想法吗?
更多信息
我添加了一个范围方法,可以过滤赞助商,因此我的查询会返回我发布日期和赞助商在前面订购的所有内容(20)。
@content = Content.for_cover
给我一些回复:
c = [s,s,s,s,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16]
其中s是"赞助"。
我必须把每一个" s"并将其移动到随机位置。
c = [c1,c2,c3,s,c4,c5,c6,c7,c8,s,c9,c10,s,c11,c12,c13,c14,s,c15,c16]
答案 0 :(得分:3)
array = [ "s1", "s2", "s3", "s4", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", "c12", "c13", "c14", "c15", "c16" ]
array.sort_by.with_index { |el, i| el =~ /s/ ? rand(array.size) : i }
#=> ["c1", "c2", "c3", "c4", "c5", "c6", "c7", "s3", "c8", "c9", "c10", "s4", "s2", "c11", "c12", "c13", "s1", "c14", "c15", "c16"]
当然,在真实应用中,您需要检查el.sponsored?
或其他内容而不是el =~ /s/
。
答案 1 :(得分:1)
编辑以回应评论:
试试这个:
sponsered = @content.delete(&:sponsered)
sponsered.each do |s|
size = @content.size
@content.insert(rand(size), s)
end
为什么不使用shuffle?
@content = Content.for_cover
@content.shuffle
示例:
array = %w[s s s c c c c c c c c c c c c c c c c]
=> ["s", "s", "s", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c"]
array.shuffle
=> ["c", "s", "c", "c", "s", "c", "c", "c", "c", "c", "s", "c", "c", "c", "c", "c", "c", "c", "c"]
答案 2 :(得分:0)
c = [ "s", "s", "s", "s", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9",
"c10", "c11", "c12", "c13", "c14", "c15", "c16" ]
hsh = c.group_by { |e| e[0] }
s = hsh.delete 's'
rest = hsh.map( &:last ).reduce :+
result = ( s + Array.new( rest.size ) ).shuffle.map do |e| e || rest.shift end
答案 3 :(得分:0)
这个(Content
类仅用于模型模拟):
class Content
attr_reader :sponsored
def initialize(sponsored)
@sponsored = sponsored
end
def inspect
sponsored.to_s
end
end
a = Array.new(4) { Content.new(true) } + Array.new(6) { Content.new(false) }
p a
#=> [true, true, true, true, false, false, false, false, false, false]
a.select(&:sponsored).each { |v| a.insert rand(a.size), a.delete(v) }
p a
#=> [true, false, true, false, false, false, true, false, false, true]
如果赞助元素总是在其他元素之前,您可以使用take_while
代替select
。