简体   繁体   English

如何在嵌套数组/哈希上使用ruby uniq

[英]How to use ruby uniq on nested array/hash

I am trying to call the uniq method on the follow json so that it would only return unique result base on employee_id 我正在尝试在follow json上调用uniq方法,以使其仅返回基于employee_id的唯一结果

# Json array
a ={
  results: [
   {
    employee: {
      name: "A",
      employee_id: "A-00016",
      title: 1
     }
   },{
    employee: {
      name: "A",
      employee_id: "A-00016",
      title: 2
     }
   },{
    employee: {
      name: "C",
      employee_id: "C-00017",
      title: 3
     }
    }
   ]
  }



# Calling uniq on a
a.uniq { |p| p.values_at(:employee_id) }

However, I am only getting this result 但是,我只得到这个结果

{
  results: [
   {
    employee: {
      name: "A",
      employee_id: "A-00016",
      title: 1
     }
    }
   ]
  }

Instead of what I want 而不是我想要的

{
  results: [
   {
    employee: {
      name: "A",
      employee_id: "A-00016",
      title: 1
     },{
    employee: {
      name: "C",
      employee_id: "C-00017",
      title: 3
     }
    }
   ]
  }

Am I using the correct method to output the result I want? 我是否使用正确的方法输出所需的结果?

With uniq : uniq

input[:results].uniq { |e| e[:employee][:employee_id] }
#⇒ [
#    {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>"1"}},
#    {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>"3"}}]

But I believe there should be some condition applied on what to choose from siblings having the same id . 但是我认为应该从具有相同id兄弟姐妹中选择什么条件。 The code below selects the one, having max title value: 下面的代码选择一个具有最大title值的代码:

input[:results].group_by { |e| e[:employee][:employee_id] }
               .map { |_, v| v.max_by { |e| e[:employee][:title].to_i } }
#⇒ [
#    {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>"2"}},
#    {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>"3"}}]

Here is one way to do this, in order to return the modified input hash , we can use uniq! 这是一种方法,为了返回修改后的输入hash ,我们可以使用uniq! which will modify the array a[:results] in place. 这将修改数组a[:results]到位。 We use dup to duplicate the hash a to preserve it, and then use tap to operate on duplicated hash. 我们使用dup复制哈希a来保留它,然后使用tap来处理重复的哈希。

r = a.dup.tap do |h|
  h[:results].uniq! do |h|
    h[:employee][:employee_id]
  end
end

#=> {:results=>
#    [
#     {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>1}},
#     {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}
#    ]
#   }
def selection_criterion(h)
  h[:title].to_i
end

{results: a[:results].group_by {|h| h[:employee][:employee_id]}.
                      values.
                      map {|arr| arr.max_by {|h|  selection_criterion(h[:employee])}}}
   #=> {:results=>
   #     [{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}},
   #      {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]}        

Define selection_criterion as desired, and possible change max_by to min_by . 根据需要定义selection_criterion ,并可能将max_by更改为min_by

The steps are as follows. 步骤如下。

 b = a[:results]
   # => [{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>1}},
   #     {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}},
   #     {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}] 
 c = b.group_by { |h| h[:employee][:employee_id] }
   #=> {"A-00016"=>[{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>1}},
   #                {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}}],
   #    "C-00017"=>[{:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]}
 d = c.values
   #=> [[{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>1}},
   #     {:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}}],
   #    [{:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]] 
 e = d.map { |arr| arr.max_by { |h| selection_criterion(h[:employee]) } }
   #=> [{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}},
   #    {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]
 { results: e }
   #=> {:results=>
   #     [{:employee=>{:name=>"A", :employee_id=>"A-00016", :title=>2}},
   #      {:employee=>{:name=>"C", :employee_id=>"C-00017", :title=>3}}]}        

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM