ruby - 如何在 Ruby 中使用键进行 deep_transform_values?
问题描述
Active Supportdeep_transform_values
递归地转换哈希的所有值。但是,是否有类似的方法可以在转换时访问值的键?
我希望能够做到以下几点:
keys_not_to_transform = ['id', 'count']
response = { result: 'ok', errors: [], data: { id: '123', price: '100.0', quotes: ['1.0', '2.0'] }, count: 10 }
response.deep_transform_values! do |key, value|
# Use value's key to help decide what to do
return value if keys_not_to_transform.any? key.to_s
s = value.to_s
if s.present? && /\A[+-]?\d+(\.\d+)?\z/.match?(s)
return BigDecimal(s)
else
value
end
end
#Expected result
# =>{:result=>"ok", :errors=>[], :data=>{:id=>"123", :price=>0.1e3, :quotes=>[0.1e1, 0.2e1]}, :count=>10}
请注意,我们对转换密钥本身不感兴趣,只是在转换相应值时将其放在手边。
解决方案
您可以像这样使用Hash#deep_merge!
(由 提供ActiveSupport
):
keys_not_to_transform = ['id', 'count']
transform_value = lambda do |value|
s = value.to_s
if s.present? && /\A[+-]?\d+(\.\d+)?\z/.match?(s)
BigDecimal(s)
else
value
end
end
transform = Proc.new do |key,value|
if keys_not_to_transform.include? key.to_s
value
elsif value.is_a?(Array)
value.map! do |v|
v.is_a?(Hash) ? v.deep_merge!(v,&transform) : transform_value.(v)
end
else
transform_value.(value)
end
end
response = { result: 'ok', errors: [], data: { id: '123', price: '100.0', quotes: ['1.0', '2.0'], other: [{id: '124', price: '17.0'}] }, count: 10 }
response.deep_merge!(response, &transform)
这输出:
#=>{:result=>"ok", :errors=>[], :data=>{:id=>"123", :price=>0.1e3, :quotes=>[0.1e1, 0.2e1], :other=>[{:id=>"124", :price=>0.17e2}]}, :count=>10}
推荐阅读
- javascript - 解析 Json 数据(来自 Azure)
- javascript - SQL 行转换为字符串格式(字符串化为文件读取格式)
- java - Android Studio 和我的设备中的分辨率相同,但外观不同
- python - 计数连续空白和分数分析。熊猫
- ffmpeg - 在这种情况下,ffmpeg 的正确命令行格式是什么
- flyway - 生产系统中的 Flyway 更改版本控制
- qt - QT Quick QML 应用程序支持多种显示尺寸
- openpyxl - 使用python循环遍历excel工作表以获取范围
- r - 使用 dplyr 根据 R 中不同事件之间的条件和日期差异删除行
- python - 使用数据计数和拆分索引导出数据帧