首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将散列数组转换为散列散列,并由散列的属性索引。

将散列数组转换为散列散列,并由散列的属性索引。
EN

Stack Overflow用户
提问于 2011-01-20 23:38:41
回答 3查看 8.4K关注 0票数 18

我有一个哈希数组,表示对象作为对API调用的响应。我需要从一些散列中提取数据,一个特定的键充当散列对象的id。我想将数组转换为一个哈希,其中键作为id,值作为原始哈希(带有该id)。

我想说的是:

代码语言:javascript
复制
api_response = [
  { :id => 1, :foo => 'bar' },
  { :id => 2, :foo => 'another bar' },
  # ..
]

ideal_response = {
  1 => { :id => 1, :foo => 'bar' },
  2 => { :id => 2, :foo => 'another bar' },
  # ..
}

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

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

我的制图方法:

代码语言:javascript
复制
keys = data.map { |x| x[:id] }
mapped = Hash[*keys.zip(data).flatten]

我情不自禁地觉得有一种更有表现力、更整洁的方法来做这件事。当需要访问的记录数量非常少时,选项2的性能非常好。映射在这里很出色,但是当响应中有很多记录时,它就开始崩溃了。谢天谢地,我预计不会有超过50-100条记录,所以映射就足够了。

是否有一种更聪明、更整洁或更有表现力的方法在Ruby?中这样做?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-20 23:55:25

Ruby <= 2.0

代码语言:javascript
复制
> Hash[api_response.map { |r| [r[:id], r] }]
#=> {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}} 

然而,散列::[]非常丑陋,打破了通常从左到右的OOP流。这就是为什么提议Enumerable#mash

代码语言:javascript
复制
> require 'facets'
> api_response.mash { |r| [r[:id], r] }
#=> {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}} 

这个基本的抽象(将枚举转换为散列)很久以前就被要求包含在Ruby中,唉,无缘

请注意,活动支持涵盖了用例:通过

Ruby >= 2.1

UPDATE仍然不爱Enumerable#mash,但是现在我们有了H。它创建了一个中间数组,但它总比什么都没有好:

代码语言:javascript
复制
> object = api_response.map { |r| [r[:id], r] }.to_h
票数 24
EN

Stack Overflow用户

发布于 2011-01-20 23:42:28

类似于:

代码语言:javascript
复制
ideal_response = api_response.group_by{|i| i[:id]} 
#=> {1=>[{:id=>1, :foo=>"bar"}], 2=>[{:id=>2, :foo=>"another bar"}]}

它使用枚举的group_by,它在集合上工作,返回任意键值的匹配值。因为它希望找到匹配的键值命中的多次出现,所以将它们附加到数组中,因此您将得到哈希数组。如果需要,可以剥离内部数组,但如果两个散列ID发生冲突,则可能会导致覆盖内容的风险。group_by通过内部数组避免了这种情况。

访问特定元素很容易:

代码语言:javascript
复制
ideal_response[1][0]       #=> {:id=>1, :foo=>"bar"}
ideal_response[1][0][:foo] #=> "bar"

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

票数 0
EN

Stack Overflow用户

发布于 2013-07-11 19:04:08

为此,我可能会去:

代码语言:javascript
复制
ideal_response = api_response.each_with_object(Hash.new) { |o, h| h[o[:id]] = o }

带块中的多个括号并不是非常漂亮,但它只对api_response进行了一次迭代就能做到这一点。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4753930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档