如果值不存在,如何合并哈希散列并设置默认值

时间:2016-11-24 16:20:48

标签: ruby hash

我需要使用 a 中的排序键将散列 a 的值合并到 out

a = {"X"=>{12=>1, 11=>4}, "Y"=>{11=>5}, "Z"=>{12=>5}}

out = [
  {"X": [4, 1]},
  {"Y": [5, 0]},
  {"Z": [0, 5]},
]

2 个答案:

答案 0 :(得分:2)

我会做这样的事情:

a = {"X"=>{12=>1, 11=>4}, "Y"=>{11=>5}, "Z"=>{12=>5}}

sorted_keys = a.values.flat_map(&:keys).uniq.sort
#=> [11, 12]
a.map { |k, v| { k => v.values_at(*sorted_keys).map(&:to_i) } }
#=> [ { "X" => [4, 1] }, { "Y" => [5, 0] }, { "Z" => [0, 5] }]

答案 1 :(得分:1)

<强>代码

def modify_values(g)
  sorted_keys = g.reduce([]) {|arr,(_,v)| arr | v.keys}.sort
  g.each_with_object({}) {|(k,v),h| h[k] = Hash.new(0).merge(v).values_at(*sorted_keys)}
end

示例

g = {"X"=>{12=>1, 11=>4}, "Y"=>{11=>5}, "Z"=>{12=>5}}
modify_values(g)
  #=> {"X"=>[4, 1], "Y"=>[5, 0], "Z"=>[0, 5]}

<强>解释

步骤如下(对于示例中的散列a)。首先从g的值中获取唯一键的数组(请参阅Enumerable#reduceArray#|),然后对该数组进行排序。

b = a.reduce([]) {|arr,(_,v)| arr | v.keys}
  #=> [12, 11] 
sorted_keys = b.sort
  #=> [11, 12]

a的第一个键值对与空哈希一起传递给each_with_object块。块变量使用并行赋值计算:

(k,v),h = [["X", {12=>1, 11=>4}], {}] 
k #=> "X" 
v #=> {12=>1, 11=>4} 
h #=> {} 

然后执行块计算。首先创建一个带有默认值 0的空哈希:

f = Hash.new(0)
  #=> {}

哈希v然后合并到f。结果是哈希,其键值对与v相同,但默认值为0。默认值的重要性在于,如果f没有键k,则f[k]会返回默认值。请参阅Hash::new

 g = f.merge(v)
   #=> {12=>1, 11=>4} 
 g.default
   #=> 0 (yup)

然后提取与sorted_keys对应的值:

 h[k] = g.values_at(*sorted_keys)
   #=> {12=>1, 11=>4}.values_at(11, 12) 
   #=> [4, 1]

a的下一个键值对传递给块时,计算如下:

(k,v),h = [["Y", {11=>5}], {"X"=>[4, 1]}] # Note `h` has been updated 
k #=> "Y" 
v #=> {11=>5} 
h #=> {"X"=>[4, 1]}
f = Hash.new(0)
  #=> {} 
g = f.merge(v)
  #=> {11=>5} 
h[k] = g.values_at(*sorted_keys)
  #=> {11=>5}.values_at(11, 12) 
  #=> [5, 0] (Note h[12] equals h's default value)

现在

h #=> {"X"=>[4, 1], "Y"=>[5, 0]} 

a的第三个键值对的计算类似。