Ruby数组的Hash解析
Ruby Array of Hash parsing
我有一个格式为的 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_names,如果缺少任何元素,则退出。
我有一个非常丑陋的双循环来检查这个,但我想收紧代码。我想我可以使用块来验证我需要的数据。这是我到目前为止的想法:
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
这是对您的代码的粗略改编,但我希望它能给您一些想法。
我会进行后续检查,同时收集错误和报告:
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]"
我有一个格式为的 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_names,如果缺少任何元素,则退出。
我有一个非常丑陋的双循环来检查这个,但我想收紧代码。我想我可以使用块来验证我需要的数据。这是我到目前为止的想法:
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
这是对您的代码的粗略改编,但我希望它能给您一些想法。
我会进行后续检查,同时收集错误和报告:
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]"