2014-04-11 94 views
0

我必須解決問題而不降低性能。Ruby:最有效的方法來隨機化陣列中某些元素的位置

我在我的社論CMS中整合了一個「贊助」內容系統。贊助內容的內容是,在某些日子裏,在我的主頁中獲得隨機位置。

我有我的內容類,有些內容有一個標誌「贊助」。

在我的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

隨機化的內容項目是否會替換現有的項目,或者只是介於兩者之間以便將其推倒? – mjnissim

+0

我的答案呢?在「建設中」之前:P – mdesantis

回答

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"] 
+0

我只需要隨機化「s」元素的順序。其他元素必須保持按日期排序! –

+0

's'元素具有哪些屬性? – dax

+0

「c」元素的相同屬性,除了旗幟「贊助」 –

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/

+0

我不需要隨機化數組,只有贊助元素。 –

+0

那麼你的例子中的'c's必須保持順序? –

+0

也可以兩個's's彼此相鄰?因爲如果他們不能確定定位不是真的隨機的話。 –

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 
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