ruby - 迭代嵌套哈希并就地修改值
问题描述
我正在尝试在不破坏 API 使用者的情况下对我们部署的一些代码进行“猴子补丁”,基本上我想找到具有键值对的参数,其值等于某个值('\u0000')并将其设置为 nil,这里是我有的 :
def traverse_param(key, value)
if value.is_a? Hash
value.each do |k, v|
return traverse_param(k, v)
end
end
if value == '\u0000'
value = nil
end
end
在 rails 5 中,我无法传递nil
给控制器,因为它将被转换为''
,我需要将nil
in 参数传递给执行以下工作的服务。
现在因为我可以有嵌套的参数,这就是我检查参数值是否为 a 的原因Hash
。我使用了这个例子:
params = {:filters=>{:user=>{:disabled_at=>"\u0000"}, :importan_param=>1}}
params.each { |k, v| traverse_param(k,v) }
我正在尝试修改该值,但它似乎不起作用?当我调试时,代码进入了正确的位置,但它没有产生预期的结果。有任何想法吗?
解决方案
因此,您面临的问题是您正在修改一个局部变量value
。如果您将整个参数散列(或子散列)传递给traverse
,那么您可以按如下方式更新值:
def traverse(params)
params.each do |k, v|
traverse(v) if v.is_a? Hash
params[k] = nil if v == '\u0000'
end
end
# => {:filters=>{:user=>{:disabled_at=>nil}, :importan_param=>1}}
transform_values
如果你是 Ruby > 2.4,你可以稍微整理一下:
def traverse(params)
params.dup.transform_values { |v| v == "\\u0000" ? nil : v.is_a?(Hash) ? traverse(v) : v }
end
traverse(params)
# => {:filters=>{:user=>{:disabled_at=>nil}, :importan_param=>1}}
params
# => {:filters=>{:user=>{:disabled_at=>"\\u0000"}, :importan_param=>1}}
或者,更具可读性:
def traverse(params)
params.dup.transform_values do |v|
next traverse(v) if v.is_a?(Hash)
v == "\\u0000" ? nil : v
end
end
希望这很有用 - 如果您有任何问题,请告诉我您的进展情况。
推荐阅读
- c - 查找 C 中 k 个最小值的索引
- c# - 从 GridView 添加 DataRow 时如何捕获 ConstraintException?
- python - 主要功能没有返回正确的结果
- java - 在 Hibernate 5.4 中无法找到 org.hibernate.service.jdbc.dialect.internal.StandardDialectResolver
- java - 如何有效地将两个数组表示的两个整数相加,将解决方案放入另一个数组
- c# - 无法获取服务主体 ID ' ' 的 Json Web Token(JWT)。异常消息:发送请求时发生错误
- express - 如何为在没有域 (.com) 的 localhost/IP 地址上运行的应用程序创建 CDN
- javascript - 单击第一个按钮后,HTML 输出未更新/计算
- streamsets - 流集:SpoolDIR_01 无法处理文件
- php - Laravel插入父子在事务中失败