【问题标题】:How would I remove a nested value from a hash that occurs multiple times如何从多次出现的哈希中删除嵌套值
【发布时间】:2020-06-29 01:00:41
【问题描述】:

我有一个哈希,就是说,

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

【问题讨论】:

  • 您应该考虑强调几天前这个问题与您的suspiciously similar question 的不同之处。
  • 嗨,是的,我会这样做。感谢@SimpleLime 的建议
  • ["FID6", "S2"]hash 的键 "within" 和键 "within" 的值,该键是散列的键,它是键 "repository" 的值,即hash 的键。这是唯一可以找到键 "within" 的地方吗,或者,例如,键 "repository" 可能有不同的名称,或者可能有更多级别的嵌套哈希?请注意,您写了["FID6", "S5"],我希望您的意思是["FID6", "S2"]

标签: ruby ruby-2.4


【解决方案1】:

代码

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"] }
  #     }
  #   }

【讨论】:

    【解决方案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

    【讨论】:

    • 谢谢@ashley。不幸的是,哈希确实有很多嵌套,但我不想发布整个哈希,因为它的页面很长。
    • 试试看。它仍然可能有效。 Ruby 的默认堆栈约为 1MB。
    • 好吧。感谢您的帮助,并会让您知道@ashley
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多