将哈希数组转换为散列哈希值,由哈希值的属性索引

cor*_*ard 16 ruby arrays hash performance

我有一个表示对象的哈希数组作为对API调用的响应.我需要从一些哈希中提取数据,并且一个特定的键用作哈希对象的id.我想将数组转换为哈希,键为ids,值为原始哈希值.

这就是我在说的:

api_response = [
  { :id => 1, :foo => 'bar' },
  { :id => 2, :foo => 'another bar' },
  # ..
]

ideal_response = {
  1 => { :id => 1, :foo => 'bar' },
  2 => { :id => 2, :foo => 'another bar' },
  # ..
}
Run Code Online (Sandbox Code Playgroud)

我有两种方法可以想到这样做.

  1. 将数据映射到ideal_response(下面)
  2. 使用api_response.find { |x| x[:id] == i }每个我需要访问记录.
  3. 我不知道的一种方法,可能涉及一种map用于构建哈希的方法,本地.

我的映射方法:

keys = data.map { |x| x[:id] }
mapped = Hash[*keys.zip(data).flatten]
Run Code Online (Sandbox Code Playgroud)

我不禁感到有一种更高效,更整洁的方式.当需要访问的记录数量非常少时,选项2非常高效.映射优于此处,但当响应中有大量记录时,它会开始崩溃.值得庆幸的是,我不希望有超过50-100条记录,因此映射就足够了.

在Ruby中有更聪明,更整洁或更高效的方法吗?

tok*_*and 22

Ruby <= 2.0

> Hash[api_response.map { |r| [r[:id], r] }]
#=> {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}} 
Run Code Online (Sandbox Code Playgroud)

但是,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"}} 
Run Code Online (Sandbox Code Playgroud)

这个基本的抽象(将枚举变为哈希)被要求在很久以前被包含在Ruby中,唉,没有运气.

Ruby> = 2.1

[更新]仍然不爱Enumerable#mash,但现在我们有阵列#to_h.不理想 - 因为我们需要一个中间阵列 - 但总比没有好:

> object = api_response.map { |r| [r[:id], r] }.to_h
Run Code Online (Sandbox Code Playgroud)