我如何从多次出现的散列中删除嵌套值

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 页长,因此我没有复制和粘贴它)。我无法拆分“存储库”所在的散列,因为它似乎嵌套在其他键值中。我现在要问的是,无论现在有多深,是否有一种方法可以在键值内匹配它。谢谢大家的建议。

假设:

  1. 只有嵌套哈希,没有数组中的哈希。
  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"] }
  #     }
  #   }