Arrays Hash解析的Ruby数组

Arrays Hash解析的Ruby数组,arrays,ruby,hash,yaml,block,Arrays,Ruby,Hash,Yaml,Block,我有一个yaml文件,格式如下: parameters: - param_name: age requires: - name - param_name: height requires: - name 基于这种格式,我希望接受键和值的散列,并确定键和值的组合是否有效。例如,基于上述示例,如果有人提交了包含以下值的哈希: {'age' => 15, 'height' => '6ft'} 它将被视为无效,因为参数名称是必需的。所以一个有效的提

我有一个yaml文件,格式如下:

parameters:
  - param_name: age
    requires:
    - name
  - param_name: height
    requires:
    - name
基于这种格式,我希望接受键和值的散列,并确定键和值的组合是否有效。例如,基于上述示例,如果有人提交了包含以下值的哈希:

{'age' => 15, 'height' => '6ft'}
它将被视为无效,因为参数名称是必需的。所以一个有效的提交看起来像

{'age' => 15, 'height' => '6ft', 'name' => 'Abe Lincoln'}.
基本上我想要的是:

对于每个参数对象,如果其下面有requires数组。检查该数组中元素的所有参数param_名称(如果有)

我有一个非常丑陋的双循环来检查这一点,但我想收紧代码。我想我可以使用块来验证我需要的数据。以下是我到目前为止的想法:

require 'yaml'
requirements = YAML.load_file('./require.yaml')
require_fields = Array.new

requirements['parameters'].each do |param|
  require_fields.concat(param['require']) if param.has_key? 'require'
end

require_fields.each do |requirement|
  found = false
  requirements['parameters'].each do |param|
    if param['param_name'] == requirement
      found = true
    end
  end
  abort "#{requirement} is a required field" unless found
end

如果你能让它更符合Ruby的习惯,你可以把它清理干净很多:

require 'yaml'
requirements = YAML.load_file('./require.yaml')

require_fields = requirements['parameters'].select do |param|
  param.has_key?('require')
end.map do |param|
  param['require']
end

require_fields.each do |requirement|
  found = requirements['parameters'].any? do |param|
    param['param_name'] == requirement
  end

  abort "#{requirement} is a required field" unless found
end
您也可以这样做:

require_fields = requirements['parameters'].map do |param|
  param['require']
end.compact
只要你的
require
是某物或
nil
,这可能就足够了

您还可以将该输入YAML转换为简单的依赖项哈希结构:

dependencies = requirements.map do ||
  [ param['param_name'], param['requires'] ]
end.to_h
然后,您可以非常轻松地进行测试:

dependencies.each do |name, requirements|
  found = requirements.find do |required_name|
    !dependencies[required_name]
  end

  abort "#{found} is a required field" unless found
end

这是对您的代码的一个非常粗略的修改,但我希望它能给您一些想法。

如果您能让它更地道一些,您可以将其清理干净:

require 'yaml'
requirements = YAML.load_file('./require.yaml')

require_fields = requirements['parameters'].select do |param|
  param.has_key?('require')
end.map do |param|
  param['require']
end

require_fields.each do |requirement|
  found = requirements['parameters'].any? do |param|
    param['param_name'] == requirement
  end

  abort "#{requirement} is a required field" unless found
end
您也可以这样做:

require_fields = requirements['parameters'].map do |param|
  param['require']
end.compact
只要你的
require
是某物或
nil
,这可能就足够了

您还可以将该输入YAML转换为简单的依赖项哈希结构:

dependencies = requirements.map do ||
  [ param['param_name'], param['requires'] ]
end.to_h
然后,您可以非常轻松地进行测试:

dependencies.each do |name, requirements|
  found = requirements.find do |required_name|
    !dependencies[required_name]
  end

  abort "#{found} is a required field" unless found
end

这是对代码的粗略修改,但我希望它能为您提供一些想法。

我将进行后续检查,收集错误并立即报告:

req = YAML.load 'parameters:
  - param_name: age
    requires:
    - name
  - param_name: height
    requires:
    - name'
input = {'age' => 15, 'height' => '6ft'}

req['parameters'].each_with_object([]) do |req, err|
  next unless input[req['param_name']] # nothing to check
  missed = req['requires'].reject { |param| input[param] }
  errors = missed.map do |param|
    [req['param_name'], param].join(' requires ')
  end
  err.concat(errors)
end
#⇒ ["age requires name", "height requires name"]
或者,链接:

req['parameters'].each_with_object(Hash.new { |h, k| h[k] = [] }) do |req, err|
  next unless input[req['param_name']] # nothing to check

  req['requires'].each do |param|
    err[param] << req['param_name'] unless input[param]
  end
end.map do |missing, required|
  "Missing #{missing} parameter, required for: [#{required.join(', ')}]"
end.join(',')
#⇒ "Missing name parameter, required for: [age, height]"
req['parameters']。每个带有_对象的_(Hash.new{| h,k | h[k]=[])do | req,err|
下一步除非输入[req['param_name']]#无需检查
req['requires']。每个do参数|

err[param]我将进行后续检查,收集错误并立即报告:

req = YAML.load 'parameters:
  - param_name: age
    requires:
    - name
  - param_name: height
    requires:
    - name'
input = {'age' => 15, 'height' => '6ft'}

req['parameters'].each_with_object([]) do |req, err|
  next unless input[req['param_name']] # nothing to check
  missed = req['requires'].reject { |param| input[param] }
  errors = missed.map do |param|
    [req['param_name'], param].join(' requires ')
  end
  err.concat(errors)
end
#⇒ ["age requires name", "height requires name"]
或者,链接:

req['parameters'].each_with_object(Hash.new { |h, k| h[k] = [] }) do |req, err|
  next unless input[req['param_name']] # nothing to check

  req['requires'].each do |param|
    err[param] << req['param_name'] unless input[param]
  end
end.map do |missing, required|
  "Missing #{missing} parameter, required for: [#{required.join(', ')}]"
end.join(',')
#⇒ "Missing name parameter, required for: [age, height]"
req['parameters']。每个带有_对象的_(Hash.new{| h,k | h[k]=[])do | req,err|
下一步除非输入[req['param_name']]#无需检查
req['requires']。每个do参数|
错误[参数]