迭代对象数组创建哈希表

20

我有一个对象,其中包含属性namedata等。我想创建一个哈希表,使用名称作为键,数据(这是一个数组)作为值。我无法弄清如何使用map减少下面的代码。是否可能?

def fc_hash
  fcs = Hash.new
  self.forecasts.each do |fc|
    fcs[fc.name] = fc.data
  end
  fcs
end

1
“map” 返回一个数组,而不是一个哈希表。但这并不意味着这段代码有什么问题。为什么不就像你已经用的那样使用它呢? - Alex Wayne
Hash[*self.forecasts.map{ [fc.name, fc.data]}.flatten] 哈希[ *self.forecasts.map { [fc.name,fc.data] }.扁平化 ] - Abid
forecasts是什么?特别是,它的类是什么? - sawa
1
@sawa 看起来合理的假设是这是一个 Forecast 实例的数组,不是吗? - Alex Wayne
在 Ruby 中,{ } 几乎总是比 Hash.new 更可取。唯一需要调用正式构造函数的原因是为了传递默认值,例如 Hash.new(0)Hash.new { |h,k| ... } - tadman
@AlexWayne 在创建一个空对象然后用块填充它的结构方面,对于数组来说是多余的,因为有 map 方法。我以为在哈希情况下有一些替代方法;很高兴知道原始代码似乎没问题! :) - João Daniel
5个回答

24

使用Hash[]方法:

Forecast = Struct.new(:name, :data)
forecasts = [Forecast.new('bob', 1), Forecast.new('mary', 2)]
Hash[forecasts.map{|forecast| [forecast.name, forecast.data]}]
# => {"mary"=>2, "bob"=>1}

14
def fc_hash
 forecasts.each_with_object({}) do |forecast, hash|
    hash[forecast.name] = forecast.data
  end
end

是的,你们两个似乎都非常喜欢它 :p - Rein Henrichs

3
我通常使用injectreduce来实现这个目的:
self.forecasts.reduce({}) do |h,e|
  h.merge(e.name => e.data)
end

1
Hash[*self.forecases.map{ [fc.name, fc.data]}.flatten]

11
工作保障:1,易读性:0。 - tadman
如果读者了解map和flatten是什么,那么这篇文章很容易阅读。 - Abid
你需要理解的不仅是 Hash[] 的含义,还有在这种情况下 * 所代表的意思。它很巧妙、简洁,但一行可能有点过于强烈了。 - tadman
3
不需要使用展开符号(splat)或flatten函数,因为Hash[]可以接受一个数组嵌套数组的形式。在map代码块中还有一些缺失的内容。 - mu is too short

0

从Ruby 2.1开始,你也可以使用Array#to_h

self.forecasts.to_h { |forecast| [forecast.name, forecast.data] }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接