Ruby 将哈希数组转换为哈希的哈希,由哈希的属性索引

Ruby 将哈希数组转换为哈希的哈希,由哈希的属性索引,ruby,arrays,performance,hash,Ruby,Arrays,Performance,Hash,我有一个哈希数组,表示对象作为对API调用的响应。我需要从一些散列中提取数据,一个特定的键用作散列对象的id。我想将数组转换成一个散列,其中键作为id,值作为原始散列,id为 下面是我要说的: api_response = [ { :id => 1, :foo => 'bar' }, { :id => 2, :foo => 'another bar' }, # .. ] ideal_response = { 1 => { :id => 1,

我有一个哈希数组,表示对象作为对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' },
  # ..
}
我有两种方法可以考虑这样做

  • 将数据映射到
    理想的\u响应
    (以下)
  • 对我需要访问的每个记录使用
    api_response.find{x|x[:id]==i}
  • 一种我不知道的方法,可能涉及到一种使用
    map
    以本机方式构建哈希的方法
  • 我的绘图方法:

    keys = data.map { |x| x[:id] }
    mapped = Hash[*keys.zip(data).flatten]
    
    我忍不住觉得有一种更高效、更整洁的方法可以做到这一点。当需要访问的记录数量非常少时,选项2的性能非常好。映射在这里非常出色,但当响应中有大量记录时,映射就开始崩溃。谢天谢地,我不希望有超过50-100条记录,所以映射就足够了

    在Ruby中有没有一种更智能、更整洁或更高效的方法呢?

    类似于:

    ideal_response = api_response.group_by{|i| i[:id]} 
    #=> {1=>[{:id=>1, :foo=>"bar"}], 2=>[{:id=>2, :foo=>"another bar"}]}
    
    它使用Enumerable的
    group_by
    ,它对集合起作用,返回您想要的任何键值的匹配项。因为它希望找到匹配键值命中的多个匹配项,所以会将它们附加到数组中,因此最终会得到哈希数组的哈希值。如果需要,可以剥离内部数组,但如果两个哈希ID发生冲突,则可能会有覆盖内容的风险
    group_by
    避免使用内部数组

    访问特定元素很容易:

    ideal_response[1][0]       #=> {:id=>1, :foo=>"bar"}
    ideal_response[1][0][:foo] #=> "bar"
    

    你在问题末尾的表现方式是另一种有效的方式。两者都相当快速和优雅

    Ruby为此,我可能会:

    ideal_response = api_response.each_with_object(Hash.new) { |o, h| h[o[:id]] = o }
    

    块中的多个括号不是非常漂亮,但它只需对api_响应进行一次迭代即可达到效果。

    这在性能和整洁性方面比我使用的映射要好,但是通过
    data[id][0]
    data[id]访问记录。首先
    有点麻烦。不过,我在这一点上吹毛求疵。让我们看看是否还有其他人愿意参加比赛。这是因为可能会遇到重复的钥匙<代码>分组依据
    是为未知数据的安全而设计的通用例程。拥有特定于应用程序的知识,例如知道您永远不会遇到重复以及随后的密钥冲突和数据丢失,将允许将数据结构简化一个级别。
    > require 'facets'
    > api_response.mash { |r| [r[:id], r] }
    #=> {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}} 
    
    > object = api_response.map { |r| [r[:id], r] }.to_h
    
    ideal_response = api_response.each_with_object(Hash.new) { |o, h| h[o[:id]] = o }