這是哈希陣列:
array = [
{:ID=>"aaa", :step2=>80},
{:ID=>"aaa", :step1=>160},
{:ID=>"aaa", :step3=>70},
{:ID=>"bbb", :step1=>80}
]
我正在嘗試將散列與相同的散列合并:ID并插入缺少的鍵值= 0,如下所示:
array = [
{:ID=>"aaa", :step1 => 160, :step2 => 80, :step3 => 70},
{:ID=>"bbb", :step1 => 80, :step2 => 0, :step3 => 0}
]
uj5u.com熱心網友回復:
這是我的解決方案:
array = [
{ID: "aaa", step2: 80},
{ID: "aaa", step1: 160},
{ID: "aaa", step3: 70},
{ID: "bbb", step1: 80}
]
def group_by_id(hashes)
# gather all IDs
ids = hashes.map { |h| h[:ID] }.uniq
keys = hashes.reduce([]) { |keys, hash| keys |= hash.keys }
default_hash = {}
keys.each do |key|
default_hash[key] = 0
end
ids.map do |id|
hashes.select { |hash| hash[:ID] == id }
.reduce(default_hash) { |reduced, hash| reduced.merge(hash) }
end
end
desired_array = [
{ID: "aaa", step1: 160, step2: 80, step3: 70},
{ID: "bbb", step1: 80, step2: 0, step3: 0}
]
output = group_by_id(array)
puts output
puts desired_array == output
uj5u.com熱心網友回復:
該#each_with_object方法在這里可能很有用。在這種情況下,我們將傳遞h為array. 然后該方法回傳該哈希值#each_with_object。
注意:||=如果左側是nil或,則將右側分配給左側false。
array.each_with_object({}) { |x, h| (h[x[:ID]] ||= {}).update(x) }
產量:
{"aaa"=>{"ID"=>"aaa", "step3"=>70, "step1"=>160, "step2"=>80},
"bbb"=>{"ID"=>"bbb", "step1"=>80}}
然后我們只需要使用#values來獲取我們想要的資料。
array
.each_with_object({}) { |x, h| (h[x[:ID]] ||= {}).update(x) }
.values
產量:
[{"ID"=>"aaa", "step3"=>70, "step1"=>160, "step2"=>80},
{"ID"=>"bbb", "step1"=>80}]
但是您希望缺少的鍵用0. 為此,我們必須知道所有密鑰是什么,然后我們才能#each_with_object再次使用。
grouped = array
.each_with_object({}) { |x, h| (h[x[:ID]] ||= {}).update(x) }
.values
all_keys = grouped.map(&:keys).flatten.uniq
grouped.map! { |h| all_keys.each_with_object(h) { |k, _h| _h[k] ||= 0 } }
現在grouped是:
[{"ID"=>"aaa", "step2"=>80, "step1"=>160, "step3"=>70},
{"ID"=>"bbb", "step1"=>80, "step2"=>0, "step3"=>0}]
uj5u.com熱心網友回復:
這可以分四個步驟完成。
array = [{:ID=>"aaa", :step2=>80}, {:ID=>"aaa", :step1=>160},
{:ID=>"aaa", :step3=>70}, {:ID=>"bbb", :step1=>80}]
在添加缺失的零值鍵之前,構造一個散列,其值是包含要回傳的所需陣列的散列
h = array.each_with_object({}) do |g,h|
h.update(g[:ID]=>g) { |_,o,n| o.merge(n)}
end
#=> {"aaa"=>{:ID=>"aaa", :step2=>80, :step1=>160, :step3=>70},
# "bbb"=>{:ID=>"bbb", :step1=>80, :step4=>40}}
請參閱Hash#update (aka merge!) 的形式,該形式采用一個塊,該塊回傳正在合并的兩個哈希中存在的鍵的值。這里的塊是:
{ |_,o,n| o.merge(n)}
塊變數_保存公共鍵的值。為該變數使用下劃線的主要原因是向讀者表明該鍵未在塊計算中使用。有關塊變數o和n.
stepX構造出現在所有元素中的所有唯一鍵的陣列array
step_keys = array.flat_map { |g| g.keys }.uniq - [:ID]
#=> [:step2, :step1, :step3, :step4]
請參閱Enumerable#flat_map。
添加缺少的鍵
step_keys.each_with_object(h) { |k,g| g.each_value { |v| v[k] ||= 0 } }?
#=> {"aaa"=>{:ID=>"aaa", :step2=>80, :step1=>160, :step3=>70, :step4=>0},
# "bbb"=>{:ID=>"bbb", :step1=>80, :step4=>40, :step2=>0, :step3=>0}}
現在
h #=> {"aaa"=>{:ID=>"aaa", :step2=>80, :step1=>160, :step3=>70, :step4=>0},
# "bbb"=>{:ID=>"bbb", :step1=>80, :step4=>40, :step2=>0, :step3=>0}}
回傳一個包含以下值的陣列h
h.values
#=> [{:ID=>"aaa", :step2=>80, :step1=>160, :step3=>70, :step4=>0},
# {:ID=>"bbb", :step1=>80, :step4=>40, :step2=>0, :step3=>0}]
這四個陳述句可以組合成一個陳述句,但我不建議這樣做,因為可讀性會受到影響,并且代碼會更難測驗。
根據要求,可以撰寫:
a = array.each_with_object({}) do |g,h|
h.update(g[:ID]=>Hash.new(0).merge(g)) { |_,o,n| o.merge(n) }
end.values
#=> [{:ID=>"aaa", :step2=>80, :step1=>160, :step3=>70},
# {:ID=>"bbb", :step1=>80, :step4=>40}]
這將回傳與以前相同的陣列,但現在:
a[0][:step4]
#=> 0
即使哈希a[0]沒有 key :step4。
請參閱Hash::new的形式,它接受一個引數但現在阻塞,引數是默認值。定義哈希時
h = Hash.new(0)
然后(可能在鍵被添加到之后h),當沒有鍵時h[k]回傳默認值。hk
在確定此變體是否滿足要求時,有明顯的考慮因素需要權衡。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/498151.html
上一篇:子類化`Struct`時添加方法
