ruby-on-rails - 合并 ruby on rails 中相同键名的值
问题描述
我想合并同名值的 id
hashes = [{
id: 3456824,
name: 'John'
},{
id: 6578954,
name: 'Vicky'
},{
id: 987456,
name: 'John'
}]
预期的:
[{
id: [3456824,987456],
name: 'John'
},{
id: 6578954,
name: 'Vicky'
}]
我如何在 ruby on rails 中实现这一点?
解决方案
这是计算所需结果的两种方法。
使用带块的Hash::new形式
hashes.each_with_object(Hash.new { |h,k| h[k] = [] }) do |g,h|
h[g[:name]] << g[:id]
end.map { |name,id| { id: id, name: name } }
#=> [{:id=>[3456824, 987456], :name=>"John"},
# {:id=>[6578954], :name=>"Vicky"}]
这个计算1的第一步是
hashes.each_with_object(Hash.new { |h,k| h[k] = [] }) do |g,h|
h[g[:name]] << g[:id]
end
#=> {"John"=>[3456824, 987456], "Vicky"=>[6578954]}
如果定义了哈希
h = Hash.new { |h,k| h[k] = [] }
并且(可能在添加键值对之后)h
没有 key k
,h[k]
在
h[k] << v
导致块{ |h,k| h[k] = [] }
被执行,导致键值对k=>[]
被添加到h
,然后<< v
被执行,h[k]
从[]
变为[k]
。
请注意,这将返回问题所要求的:id=>[6578954]
,而不是。:id=>6578954
将所有值都:id
返回一个数组可以避免在:id
处理此操作的返回值的后续代码中检查是否返回一个数组或整数。
如果:id=>6578954
, 是需要的,可以写
hashes.each_with_object(Hash.new { |h,k| h[k] = [] }) do |g,h|
h[g[:name]] << g[:id]
end.transform_values { |v| v.size==1 ? v.first : v }.
map { |name,id| { id: id, name: name } }
#=> [{:id=>[3456824, 987456], :name=>"John"},
# {:id=>6578954, :name=>"Vicky"}]
使用Hash#update (aka merge!
) 的形式,它使用一个块来确定合并的两个哈希中存在的键的值
arr.each_with_object({}) do |g,h|
h.update(g[:name]=>[g[:id]]) { |_,o,n| o+n }
end.map { |name,id| { id: id, name: name } }
#=> [{:id=>[3456824, 987456], :name=>"John"},
# {:id=>[6578954], :name=>"Vicky"}]
如果需要:id=>6578954
,而不是:id=>[6578954]
,则:
arr.each_with_object({}) do |g,h|
h.update(g[:name]=>g[:id]) { |_,o,n| [*o,n] }
end.map { |name,id| { id: id, name: name } }
#=> [{:id=>[3456824, 987456], :name=>"John"},
# {:id=>6578954, :name=>"Vicky"}]
请注意,这里update
的论点是g[:name]=>g[:id]
之前g[:name]=>[g[:id]]
的。
第一步如下。
arr.each_with_object({}) do |g,h|
h.update(g[:name]=>g[:id]) { |_,o,n| [*o,n] }
end
#=> {"John"=>[3456824, 987456], "Vicky"=>6578954}
一般来说,当可以使用Enumerable#group_by时,可以采用其中一种或两种方法。反之亦然。这些方法中的选择是个人品味的问题。
1. 此计算的第一部分的变体是hashes.each_with_object({}) { |g,h| (h[g[:name]] ||= []) << g[:id] } #=> {"John"=>[3456824, 987456], "Vicky"=>[6578954]}
。
推荐阅读
- cordova - 在科尔多瓦上使用 admob 的 Google 同意 SDK
- c# - Mac OSX、ASP.NET 和 mySQL - 密钥长度错误
- php - 无法从 google API 获取用户信息
- r - 使用 dplyr 在多个子集上运行 rma()
- r - 如何根据另一列中存在的数据计算列中特定值的出现次数?
- javascript - 在 ReactJS 中重新创建单选按钮行为
- python - python - 如何使用pandas python找到数据框坐标中的最低左值和下值?
- bash - 每个进程的内存使用情况
- machine-learning - 反向传播与 Levenberg Marquardt
- ios - BUG:隐藏/显示一次排列在堆栈视图中的多个视图