Ruby在哈希中查找键的数据类型

时间:2014-08-19 15:30:24

标签: ruby hash

我有一个非常不同的哈希,具体取决于yaml文件中的内容。这是两种可能的结构。

config = {'points' => {2012 => 5.5, 2013 => 6.3}}

config = {'points' => {'method' => 'calculate_periodicaly', 'default' => 10}}

第一个将始终将日期作为键,第二个将具有方法和默认键。

我想将它传递给一个方法,具体取决于它是如何构建的。我有类似的东西,以确定它是否有多年的钥匙

config.is_a?(Hash) && config['points'].has_key?(2012) && config['points'].has_key?(2013)
=> true

我可以为它构建的其他方式做类似的事情。但对我来说这是丑陋的代码。我想做一些事情,它可以找出每个键的数据类型。因此,如果所有键都是数字,那么它应该是日期哈希,如果所有键都是字符串,那么它应该是字符串哈希。

我试过这样的事情

config.is_a?(Hash) && config['points'].keys.each {|key| key.is_a? Integer}

但这只是返回

=> [
   [0] 2012,
   [1] 2013
]

有更好的方法吗?或许更Ruby的方式呢?

更新

我们检查它的哈希是有时它也可以被称为文字的原因。这里有点yaml

 homeowner_policies:
  total: active_homeowne
  actual: qualifing_homeowner
  points: 
    method: calculated_points_by_selected_policies
    default: 0
  target: homeowner_industry_target_agaist_market_share
  description: Property / Homeowners

这个例子它将点构建成一个哈希,methoddefault是密钥。在哈希中呈现内容的gem。但如果你只想指定直接金额,你可以指定类似这样的东西

 homeowner_policies:
  conditional: include_homeowner?
  total: active_homeowne
  actual: qualifing_homeowner
  points: 10
  target: homeowner_industry_target_agaist_market_share
  description: Property / Homeowners

然后第三种可能性是逐年的,所以就像第一个例子一样,但你可以提供多年,每年可以给出不同的分数。

这将用于决定使用数据的方法。

如果这些点基于年份,则类中的requires_parsing?方法将返回true,该类将解析数据。如果没有,那么另一个班级会等等。

2 个答案:

答案 0 :(得分:1)

分别使用all?

config.is_a?(Hash) && config['points'].keys.all? {|key| key.is_a? Integer}

注意:您有没有理由查看配置是否为哈希?如果它来自yml文件,那么这是多余的。

要判断是否有更好的方法,您需要显示您想要传递给它的方法,以及您计划如何调用它。

答案 1 :(得分:1)

这是一种简单的方法(显然有广泛的应用)。

<强>代码

def confirm_key_type(h, key, klass)
  h[key].keys.all? { |k| klass === k } rescue nil
end

def confirm_key_type(h, key, klass)
  begin
    h[key].keys.all? { |k| klass === k }
  rescue
    nil
  end
end

第一种形式称为“内联救援”。它受到一些人的喜爱hated by others。在第二种形式中,您当然可以拯救相关的例外(NoMethodErrorTypeError等)。

也可以将该块写为{ |k| k.class == k }{ |k| k.is_a? k }

<强>实施例

config = {'points' => {2012 => 5.5, 2013 => 6.3}}
  #=> {"points"=>{2012=>5.5, 2013=>6.3}}

confirm_key_type(config, 'points', Fixnum)     #=> true
confirm_key_type(config, 'points', String)     #=> false

config = {'points' => {'method' => 'calculate_periodicaly', 'default' => 10}}
  #=> {"points"=>{"method"=>"calculate_periodicaly", "default"=>10}}

confirm_key_type(config, 'points', Fixnum)     #=> false
confirm_key_type(config, 'points', String)     #=> true

confirm_key_type(config, 'cats', Fixnum)       #=> nil
confirm_key_type(config, :dogs, String)        #=> nil

confirm_key_type([1,2,3], 'points', Fixnum)    #=> nil
confirm_key_type('goldfish', 'points', String) #=> nil
confirm_key_type(nil, 'points', String)        #=> nil