我有一个散列数组,表示对象作为对 API 调用的响应。我需要从一些散列中提取数据,一个特定的键用作散列对象的 id。我想将数组转换为散列,其中键作为 ID,值作为具有该 ID 的原始散列。
我说的是:
api_response = [
{ :id => 1, :foo => 'bar' },
{ :id => 2, :foo => 'another bar' },
# ..
]
ideal_response = {
1 => { :id => 1, :foo => 'bar' },
2 => { :id => 2, :foo => 'another bar' },
# ..
}
我可以想到两种方法。
- 将数据映射到
ideal_response
(下) - 使用
api_response.find { |x| x[:id] == i }
我需要访问的每条记录。 - 一种我不知道的方法,可能涉及一种使用
map
原生构建哈希的方法。
我的映射方法:
keys = data.map { |x| x[:id] }
mapped = Hash[*keys.zip(data).flatten]
我不禁觉得有一种更高效、更整洁的方法可以做到这一点。当需要访问的记录数量非常少时,选项 2 的性能非常好。映射在这里表现出色,但当响应中有大量记录时它开始崩溃。值得庆幸的是,我预计不会有超过 50-100 条记录,因此映射就足够了。
在 Ruby 中是否有更智能、更简洁或更高效的方法来执行此操作?
最佳答案
ruby <= 2.0
> Hash[api_response.map { |r| [r[:id], r] }]
#=> {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}}
然而,Hash::[]非常丑陋,打破了通常的从左到右的 OOP 流程。这就是为什么 Facets建议Enumerable#mash :
> require 'facets'
> api_response.mash { |r| [r[:id], r] }
#=> {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}}
这个基本抽象(将可枚举值转换为哈希值)很久以前就被要求包含在 Ruby 中,唉,without luck .
请注意,您的用例由 Active Support 涵盖:Enumerable#index_by
ruby >= 2.1
[更新] 仍然不喜欢 Enumerable#mash
,但现在我们有 Array#to_h .它创建了一个中间数组,但总比没有好:
> object = api_response.map { |r| [r[:id], r] }.to_h
关于ruby - 将哈希数组转换为哈希哈希,由哈希的属性索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4753930/