[英]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.