在条件中合并Array中的两个项目

时间:2014-04-12 12:54:24

标签: ruby

我有一个带有哈希对象的数组。该数组如下所示:

[
  {"name"=>"Red", "id"=>177, "shades"=>[{"shade"=>"light", "id"=>355}], "owner"=>false},
  {"name"=>"Red", "id"=>195, "shades"=>[{"shade"=>"dark", "id"=>135}],"owner"=>true},
  {"name"=>"Green", "id"=>192, "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true},
  {"name"=>"Blue", "id"=>191, "shades"=>[{"shade"=>"pale", "id"=>137}], "owner"=>true}
]

我想将name的哈希值合并到owner=>true的哈希值中。因此,在上面,因为有两个Red shadesowner=>true合并为一个,同时保留[ {"name"=>"Red", "id"=>195, "shades"=>[{"shade"=>"dark", "id"=>135}, {"shade"=>"light", "id"=>355}],"owner"=>true}, {"name"=>"Green", "id"=>192, "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true}, {"name"=>"Blue", "id"=>191, "shades"=>[{"shade"=>"light", "id"=>137}], "owner"=>true} ]

的属性

最后看起来像这样:

{{1}}

我该怎么做?我应该迭代数组,同时将颜色名称保存在一个唯一的集合中吗?

3 个答案:

答案 0 :(得分:4)

解决方案:

ary = [                                                                                
  {"name"=>"Red", "id"=>177, "shades"=>[{"shade"=>"light", "id"=>355}], "owner"=>false},                                                                                  
  {"name"=>"Red", "id"=>195, "shades"=>[{"shade"=>"dark", "id"=>135}],"owner"=>true},
  {"name"=>"Green", "id"=>192, "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true},                                                                                  
  {"name"=>"Blue", "id"=>191, "shades"=>[{"shade"=>"pale", "id"=>137}], "owner"=>true }                                                                                    
]  

ary.group_by { |h| h['name']}.values.map{ |ary| 
  ary.sort_by{ |h| h['owner'] ? 1 : 0 }.inject { |merged, new| 
    merged.merge(new) {|key, old, new| key == 'shades' ? old + new : new }
  }
}

结果:

注意:我认为您不关心阴影键下的订单

[
  {"name"=>"Red", "id"=>195, "shades"=>[{"shade"=>"light", "id"=>355}, {"shade"=>"dark", "id"=>135}], "owner"=>true}, 
  {"name"=>"Green", "id"=>192, "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true}, 
  {"name"=>"Blue", "id"=>191, "shades"=>[{"shade"=>"pale", "id"=>137}], "owner"=>true}
]

阐释:

首先,您需要按名称对数据进行分组。 group_by完全按照它的声音执行 - 它返回一个散列,其中键是块结果,值是ary的所有元素,给出了一些结果。不需要密钥,因此我们只需调用values来获取数组数组。

现在每个内部数组都包含需要合并为一个的所有哈希值。 merge采用可选块来决定如果两个哈希值具有相同的键(默认情况下会用新值覆盖它),该怎么做。我已经决定先对数组进行排序,因此owner => true的数组是最后一个要合并的数组。然后传递给merge的块只需要检查密钥是否为'shades'并给出该密钥的给定数组的总和,其余的则使用新值。

答案 1 :(得分:2)

j = [                                                                                
  {"name"=>"Red", "id"=>177, "shades"=>[{"shade"=>"light", "id"=>355}], "owner"=>false},                                                                                  
  {"name"=>"Red", "id"=>195, "shades"=>[{"shade"=>"dark", "id"=>135}],"owner"=>true},
  {"name"=>"Green", "id"=>192, "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true},                                                                                  
  {"name"=>"Blue", "id"=>191, "shades"=>[{"shade"=>"pale", "id"=>137}], "owner"=>true
}                                                                                    
]                                                                                    

使用Enumerable#each_with_object,块的返回值作为第二个参数传递给块,而第一个参数是来自yielded的{​​{1}}对象(array在这个答案中),第一次循环运行第二个参数(j)被设置为提供给arr的参数,这是一个空数组(each_with_object

[]

答案 2 :(得分:0)

这是另一种方法:

<强>代码

owners, nonowners = ary.partition { |h| h["owner"] }
h = owners.each_with_object({}) { |g,h| h[g["name"]] = g }
nonowners.each { |g| h[g["name"]]["shades"] << (g["shades"].first) }
h.values

<强>解释

ary = [                                                                                
  {"name"=>"Red",   "id"=>177, "shades"=>[{"shade"=>"light", "id"=>355}],
   "owner"=>false},
  {"name"=>"Red",   "id"=>195, "shades"=>[{"shade"=>"dark",  "id"=>135}],
   "owner"=>true},
  {"name"=>"Green", "id"=>192, "shades"=>[{"shade"=>"pale",  "id"=>135}],
   "owner"=>true},
  {"name"=>"Blue",  "id"=>191, "shades"=>[{"shade"=>"pale",  "id"=>137}],
   "owner"=>true}
]  

首先将数组划分为一个包含所有者哈希值的数组和一个包含非所有者哈希值的第二个数组。

owners, nonowners = ary.partition { |h| h["owner"] }
  # owners=>
  #  [{"name"=>"Red", "id"=>195,
  #    "shades"=>[{"shade"=>"dark", "id"=>135}], "owner"=>true}, 
  #   {"name"=>"Green", "id"=>192,
  #    "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true},
  #   {"name"=>"Blue", "id"=>191,
  #    "shades"=>[{"shade"=>"pale", "id"=>137}], "owner"=>true}],
  # nonowners=> 
  #  [{"name"=>"Red", "id"=>177,
  #    "shades"=>[{"shade"=>"light", "id"=>355}], "owner"=>false}]]

接下来,构造一个哈希,其值为owner数组中的哈希值,其键值为&#34; name&#34;这些哈希的属性(即&#34;红色&#34;,&#34;绿色&#34;和&#34;蓝色&#34;)。

h = owners.each_with_object({}) { |g,h| h[g["name"]] = g }
  #=> {"Red"=>{"name"=>"Red", "id"=>195,
  #      "shades"=>[{"shade"=>"dark", "id"=>135}], "owner"=>true},
  #    "Green"=>{"name"=>"Green", "id"=>192,
  #      "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true},
  #    "Blue"=>{"name"=>"Blue", "id"=>191,
  #      "shades"=>[{"shade"=>"pale", "id"=>137}], "owner"=>true}}

现在添加&#34;阴影&#34;每个非所有者哈希的属性为密钥&#34;名称&#34;。

的相应所有者哈希
nonowners.each { |g| h[g["name"]]["shades"] << (g["shades"].first) }

h现在是:

h #=> {"Red"  =>{"name"=>"Red", "id"=>195,
  #      "shades"=>[{"shade"=>"dark","id"=>135}, {"shade"=>"light","id"=>355}],
  #      "owner"=>true},
  #    "Green"=>{"name"=>"Green", "id"=>192,
  #      "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true},
  #    "Blue"=>{"name"=>"Blue", "id"=>191,
  #      "shades"=>[{"shade"=>"pale", "id"=>137}], "owner"=>true}}

最后,从此哈希中提取值。

h.values
  #=> [{"name"=>"Red", "id"=>195,
  #     "shades"=>[{"shade"=>"dark","id"=>135}, {"shade"=>"light","id"=>355}],
  #     "owner"=>true},
  #    {"name"=>"Green", "id"=>192,
  #     "shades"=>[{"shade"=>"pale", "id"=>135}], "owner"=>true},
  #    {"name"=>"Blue", "id"=>191,
  #     "shades"=>[{"shade"=>"pale", "id"=>137}], "owner"=>true}]