我如何从多次出现的散列中删除嵌套值
How would I remove a nested value from a hash that occurs multiple times
我有一个哈希表,
hash = {"lock_version"=>4,
"exhibition_quality"=>false,
"within"=>["FID6", "S2"],
"repository"=>
{"ref"=>"/repositories/2",
"repository"=>{"ref"=>"/repositories/2",
"within"=>["FID6", "S2"]
}
}
此散列已通过另一个函数传递。如何从“within”=>[“FID6”,“S5”]中删除一个具有模式 FID 的值(在本例中为 FID6)而不改变原始哈希值?这只是哈希的缩短版本,但还有其他实例,其中哈希超长并且“内部”键值对出现多次。注意:本程序使用ruby 2.4
我被要求澄清这个问题与我之前提出的问题有何不同,所以这是一个更多的澄清,因为从那以后我做了更多的工作。这个特定的键值对“within”=>[“FID6”,“S2”],现在出现了深度嵌套(整个散列大约有 2 页长,因此我没有复制和粘贴它)。我无法拆分“存储库”所在的散列,因为它似乎嵌套在其他键值中。我现在要问的是,无论现在有多深,是否有一种方法可以在键值内匹配它。谢谢大家的建议。
假设:
- 只有嵌套哈希,没有数组中的哈希。
- 哈希中没有对象。
这适用于您的示例,也适用于我根据上述假设创建的示例:
cloned_hash = Marshal.load(Marshal.dump(hash))
def remove_key_value_pair(key, value, hash)
if hash.key?(key) && hash[key] == value
hash.delete(key)
end
hash.each{|k, v| remove_key_value_pair(key, value, v) if v.is_a? Hash }
end
# call with
remove_key_value_pair("within", ["FID6", "S2"], cloned_hash)
如果散列有很多嵌套,这将 运行 变成 SystemStackError
。
代码
def defidder(h)
h.each_with_object({}) do |(k,v),h|
h[k] =
case v
when Array
v.reject { |s| s.match?(/\AFID\d+\z/) } if k == "within"
when Hash
defidder(v)
else
v
end
end
end
例子
我在问题中给出的示例中添加了另一层哈希嵌套:
hash = {
"lock_version"=>4,
"exhibition_quality"=>false,
"within"=>["FID6", "S2"],
"repository"=>{
"ref"=>"/repositories/2",
"repository"=>{"ref"=>"/repositories/2"},
"within"=>["FID6", "S2"],
"1more"=>{ a: 1, "within"=>["FID999", "S7"] }
}
}
defidder hash
#=> {
# "lock_version"=>4,
# "exhibition_quality"=>false, "within"=>["S2"],
# "repository"=>{
# "ref"=>"/repositories/2",
# "repository"=>{"ref"=>"/repositories/2"},
# "within"=>["S2"],
# "1more"=>{:a=>1, "within"=>["S7"]
# }
# }
我们可以验证 hash
没有发生突变。
hash
#=> {
# "lock_version"=>4,
# "exhibition_quality"=>false,
# "within"=>["FID6", "S2"],
# "repository"=>{
# "ref"=>"/repositories/2",
# "repository"=>{"ref"=>"/repositories/2"},
# "within"=>["FID6", "S2"],
# "1more"=>{ a: 1, "within"=>["FID999", "S7"] }
# }
# }
我有一个哈希表,
hash = {"lock_version"=>4,
"exhibition_quality"=>false,
"within"=>["FID6", "S2"],
"repository"=>
{"ref"=>"/repositories/2",
"repository"=>{"ref"=>"/repositories/2",
"within"=>["FID6", "S2"]
}
}
此散列已通过另一个函数传递。如何从“within”=>[“FID6”,“S5”]中删除一个具有模式 FID 的值(在本例中为 FID6)而不改变原始哈希值?这只是哈希的缩短版本,但还有其他实例,其中哈希超长并且“内部”键值对出现多次。注意:本程序使用ruby 2.4
我被要求澄清这个问题与我之前提出的问题有何不同,所以这是一个更多的澄清,因为从那以后我做了更多的工作。这个特定的键值对“within”=>[“FID6”,“S2”],现在出现了深度嵌套(整个散列大约有 2 页长,因此我没有复制和粘贴它)。我无法拆分“存储库”所在的散列,因为它似乎嵌套在其他键值中。我现在要问的是,无论现在有多深,是否有一种方法可以在键值内匹配它。谢谢大家的建议。
假设:
- 只有嵌套哈希,没有数组中的哈希。
- 哈希中没有对象。
这适用于您的示例,也适用于我根据上述假设创建的示例:
cloned_hash = Marshal.load(Marshal.dump(hash))
def remove_key_value_pair(key, value, hash)
if hash.key?(key) && hash[key] == value
hash.delete(key)
end
hash.each{|k, v| remove_key_value_pair(key, value, v) if v.is_a? Hash }
end
# call with
remove_key_value_pair("within", ["FID6", "S2"], cloned_hash)
如果散列有很多嵌套,这将 运行 变成 SystemStackError
。
代码
def defidder(h)
h.each_with_object({}) do |(k,v),h|
h[k] =
case v
when Array
v.reject { |s| s.match?(/\AFID\d+\z/) } if k == "within"
when Hash
defidder(v)
else
v
end
end
end
例子
我在问题中给出的示例中添加了另一层哈希嵌套:
hash = {
"lock_version"=>4,
"exhibition_quality"=>false,
"within"=>["FID6", "S2"],
"repository"=>{
"ref"=>"/repositories/2",
"repository"=>{"ref"=>"/repositories/2"},
"within"=>["FID6", "S2"],
"1more"=>{ a: 1, "within"=>["FID999", "S7"] }
}
}
defidder hash
#=> {
# "lock_version"=>4,
# "exhibition_quality"=>false, "within"=>["S2"],
# "repository"=>{
# "ref"=>"/repositories/2",
# "repository"=>{"ref"=>"/repositories/2"},
# "within"=>["S2"],
# "1more"=>{:a=>1, "within"=>["S7"]
# }
# }
我们可以验证 hash
没有发生突变。
hash
#=> {
# "lock_version"=>4,
# "exhibition_quality"=>false,
# "within"=>["FID6", "S2"],
# "repository"=>{
# "ref"=>"/repositories/2",
# "repository"=>{"ref"=>"/repositories/2"},
# "within"=>["FID6", "S2"],
# "1more"=>{ a: 1, "within"=>["FID999", "S7"] }
# }
# }