2014-05-04 44 views
0

我正在構建Sinatra/Mongoid應用程序,我想在MongoDB的文檔中創建一個數組值的動態菜單。我想下面的算法:
Supose在蒙戈存儲一些文件 在Sinatra Mongoid的動態菜單

{ "name": "doc1", "array": ["foo", "bar", "baz", "quux"] } 
{ "name": "doc2", "array": ["foo", "baz"] } 
{ "name": "doc3", "array": ["bar", "baz", "quux"] } 
{ "name": "doc4", "array": ["quux"] } 
{ "name": "doc5", "array": ["foo", "quux"] } 

現在,我想這應該

  1. 要求所有文檔的「數組」字段值,
  2. 然後排序中值提及次數,
  3. 刪除重複值
  4. 並給我這個新的rray在我看來,建立%ul,就像這樣:

    %ul 
        %li foo 
        %li bar 
        %li baz 
        %li quux 
    

而且我有不知道如何實現這一點。

非常感謝您的幫助。

+0

我不知道我是否完全理解你的問題。你可以添加一個HTML/HAML /任何片段與上面的示例輸入所需的輸出? – DMKE

+0

類似[this](http:// pastebin。com/VstFPk04) – askhat

+0

我已經將你的代碼片段納入你的問題。 – DMKE

回答

0

假設你已經有一個arrays變量與文檔的「數組」的價值觀:

arrays = [ 
    ["foo", "bar", "baz", "quux"], 
    ["foo", "baz"], 
    ["bar", "baz", "quux"], 
    ["quux"], 
    ["foo", "quux"] 
] 

在這種情況下,我會使用一個哈希存儲陣列值爲鍵,以及一個計數器值。這允許

  1. 消除雙項和
  2. 排序創建一個句柄。

有趣位是inject方法,其中在一個可枚舉迭代並注入一個accumolator(memo):

list = arrays.flatten.inject({}) do |memo, e| 
    memo[e] = (memo[e] || 0) + 1 
    memo 
end 
#=> [["foo", 3], ["bar", 2], ["baz", 3], ["quux", 4]] 

這產生本list其然後可以進行排序:

list = list.sort{|a,b| a[1] <=> b[1] } 
#=> [["bar", 2], ["foo", 3], ["baz", 3], ["quux", 4]] 

並過濾:

list = list.map(&:first) 
#=> ["bar", "foo", "baz", "quux"] 

然後您可以遍歷視圖中的該數組。


N.B.我通常會盡量多一點壓縮inject呼叫,像這樣

list = arrays.flatten.inject({}) do |memo, e| 
    (memo[e] ||= 0) += 1 
    memo 
end 

list = arrays.flatten.inject(Hash.new {|h,k| h[k]=0 }) do |memo, e| 
    memo[e] += 1 
    memo 
end 

...但由於某些原因,我的紅寶石目前認爲這是一個語法錯誤。也許這只是缺乏咖啡;-)