代碼
def group(h,n)
h.each_slice(n).with_object({}) do |a,g|
key = a[(a.size-1)/2].first
a.each {|k,f| g.update(key=>f) {|_,oh,nh| oh.merge(nh) {|_,ov,nv| ov+nv}}}
end
end
這不會發生變異h
。
例
爲了證明代碼我將使用含有鍵文字的散列。
h = {
:timestamp1 => { :attr1 => 1, :attri2 => 2, :attr3 => 3},
:timestamp2 => { :attr1 => 1, :attri2 => 2, :attr3 => 3},
:timestamp3 => { :attr1 => 1, :attri2 => 2, :attr3 => 3},
:timestamp4 => { :attr1 => 4, :attri2 => 5, :attr3 => 6},
:timestamp5 => { :attr1 => 4, :attri2 => 5, :attr3 => 6},
:timestamp6 => { :attr1 => 4, :attri2 => 5, :attr3 => 6},
}
group(h,1) == h
#=> true
group(h,2)
#=> {:timestamp1=>{:attr1=>2, :attri2=>4, :attr3=>6},
# :timestamp3=>{:attr1=>5, :attri2=>7, :attr3=>9},
# :timestamp5=>{:attr1=>8, :attri2=>10, :attr3=>12}}
group(h,3)
#=> {:timestamp2=>{:attr1=>3, :attri2=>6, :attr3=>9},
# :timestamp5=>{:attr1=>12, :attri2=>15, :attr3=>18}}
group(h,4)
#=> {:timestamp2=>{:attr1=>7, :attri2=>11, :attr3=>15},
# :timestamp5=>{:attr1=>8, :attri2=>10, :attr3=>12}}
group(h,5)
#=> {:timestamp3=>{:attr1=>11, :attri2=>16, :attr3=>21},
# :timestamp6=>{:attr1=>4, :attri2=>5, :attr3=>6}}
group(h,6)
#=> {:timestamp4=>{:attr1=>15, :attri2=>21, :attr3=>27}}
說明
我已經使用的Hash#update(又名Hash.merge!
)和Hash#merge僱用一個塊,以確定存在於被合併兩個散列密鑰的值的形式。 (「舊值」),nh
(「新值」),ov
(「舊值」)和nv
(「新值」)參見文檔以解釋塊變量_
(常用密鑰),oh
。
步驟如下。
n = 3
enum0 = h.each_slice(n)
#=> #<Enumerator: {:timestamp1=>{:attr1=>1, :attri2=>2, :attr3=>3},
# :timestamp2=>{:attr1=>1, :attri2=>2, :attr3=>3},
# ...
# :timestamp6=>{:attr1=>4, :attri2=>5, :attr3=>6}}
# :each_slice(3)>
enum1 = enum0.with_object({})
#=> #<Enumerator:
# #<Enumerator: {:timestamp1=>{:attr1=>1, :attri2=>2, :attr3=>3},
# :timestamp2=>{:attr1=>1, :attri2=>2, :attr3=>3},
# ...
# :timestamp6=>{:attr1=>4, :attri2=>5, :attr3=>6}}
# :each_slice(3)>:with_object({})>
我們可以檢查將被enum1
通過轉換enum1
到一個陣列產生並傳遞到該塊中的(二)的元件。
enum1.to_a
#=> [
# [
# [
# [:timestamp1, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp2, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp3, {:attr1=>1, :attri2=>2, :attr3=>3}]],
# {}
# ],
# [
# [
# [:timestamp4, {:attr1=>4, :attri2=>5, :attr3=>6}],
# [:timestamp5, {:attr1=>4, :attri2=>5, :attr3=>6}],
# [:timestamp6, {:attr1=>4, :attri2=>5, :attr3=>6}]],
# {}
# ]
# ]
空數組由塊變量g
表示。該方法將構建並返回。將由enum1
生成的第一個元素傳遞給該塊,並使用並行分配分配兩個塊變量。
a,g = enum1.next
#=> [
# [
# [:timestamp1, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp2, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp3, {:attr1=>1, :attri2=>2, :attr3=>3}]
# ]
# {}
# ]
a #=> [
# [:timestamp1, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp2, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp3, {:attr1=>1, :attri2=>2, :attr3=>3}]
# ]
g #=> {}
現在可以執行塊計算。
key = a[(a.size-1)/2].first
#=> a[2].first
#=> [:timestamp2, {:attr1=>1, :attri2=>2, :attr3=>3}].first
#=> :timestamp2
enum2 = a.each
#=> #<Enumerator: [[:timestamp1, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp2, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp3, {:attr1=>1, :attri2=>2, :attr3=>3}]]
# :each>
enum2.to_a # for display purposes only
#=> [[:timestamp1, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp2, {:attr1=>1, :attri2=>2, :attr3=>3}],
# [:timestamp3, {:attr1=>1, :attri2=>2, :attr3=>3}]]
k,f = enum2.next
#=> [:timestamp1, {:attr1=>1, :attri2=>2, :attr3=>3}]
k #=> :timestamp1
f #=> {:attr1=>1, :attri2=>2, :attr3=>3}
g.update(key=>f) {|_,oh,nh|
oh.merge(nh) {|_,ov,nv| g.update(key=>f) {|_,oh,nh| oh.merge(nh) {|_,ov,nv| ov+nv}}}}
#=> g.update(:timestamp2=>{:attr1=>1, :attri2=>2, :attr3=>3}) {|_,oh,nh|
# oh.merge(nh) {|_,ov,nv| ov+nv}}}}
#=> {:timestamp2=>{:attr1=>1, :attri2=>2, :attr3=>3}}
然後
k,f = enum2.next
#=> [:timestamp2, {:attr1=>1, :attri2=>2, :attr3=>3}]
k #=> :timestamp2
f #=> {:attr1=>1, :attri2=>2, :attr3=>3}
g.update(key=>f) {|_,oh,nh| oh.merge(nh) {|_,ov,nv| ov+nv}}
# g.update(:timestamp2=>{:attr1=>1, :attri2=>2, :attr3=>3} {|_,oh,nh|
# oh.merge(nh) {|_,ov,nv| ov+nv}}
#=> {:timestamp2=>{:attr1=>2, :attri2=>4, :attr3=>6}}
其餘的計算是相似的。
1公用密鑰用下劃線表示,表示它在塊計算中不使用。
當你給出一個例子時,給每個輸入分配一個變量是很有幫助的(例如'h = {timestamp1 => ...')。這樣,讀者可以引用變量(例如'h'),而不必定義它。其次,沒有'......'。請。完成示例並顯示期望的結果,以便提供解決方案的人員可以演示其代碼生成結果。儘可能縮短範例,但仍然覆蓋基地。 –
你所說的數組是散列。您的散列鍵似乎是未標註的局部變量或方法。您需要顯示這些變量或方法的代碼,或者將鍵全部寫成文字(例如符號或字符串)。無論如何,散列必須是有效的Ruby對象。當散列的大小不是組大小的倍數時,您還需要告訴我們您需要什麼,以及每個組中元素的數量是多少時使用哪個鍵。例如,如果該組有四個元素,那麼我們應該使用組的第二個還是第三個元素的鍵? –
@CarySwoveland是的,這是一個散列,對不起,在思考之前打字。但其餘的,正如我所說,這是示例代碼,而不是我實際做的或完成的。我完全知道,這些不是有效的散列鍵。就像我說的,我不需要糾正這些代碼。同樣對於答案,無論你使用大小合適的散列表做什麼都沒有關係,因爲你們都不是在這裏寫我的代碼,只是爲了幫助我以正確的方式;-)但無論如何謝謝你看我的情況! –