【问题标题】:symbolizing and replacing a value in hash values in hash of array of hash在散列数组的散列中符号化和替换散列值中的值
【发布时间】:2020-09-29 06:31:11
【问题描述】:

我有一个类似的数据结构

  lib_data = {'library'=>[{"type"=>"Books", 
  "checkout"=>false, "data"=>[{"type"=>"Books", "operator"=>"AND", "details"=>{"property"=>"Name", "author"=>"%s", 
  "name"=>"%s"}}, {"type"=>"Books", "criteria"=>{"property"=>"Revision", "operator"=>"%s", 
  "value"=>"%s"}}]}]}

我正在尝试首先符号化所有键,然后将值插入由 inplace of %s 表示的键中

我能够将一小段代码猴子修补到 Hash 类中,这将使我能够使用类似这样的东西来符号化所有哈希值

def symbolize_all_keys
    keys.each do |k|
      key = k.to_sym
      value = delete(k)
      store(key, value)
    end
    self
  end

然后只使用lib_data.symbolize_all_keys 但这象征着一把钥匙

有没有更惯用的方式来象征所有的钥匙?

还想要一种将值插入到具有 %s 个值的键中的方法吗?

【问题讨论】:

  • Rails 有 Hash#deep_symbolize_keys 或者像 deep_hash_transformer 这样的 gem 可以满足您的需求:递归地转换哈希中的键。即使您不使用 Rails 并且不想包含更多 gem,您也可能希望在其源代码中了解这些 gem 的工作原理。

标签: ruby hash-of-hashes


【解决方案1】:

您可以以递归方式使用Hash#transform_keys!,例如:

def symbolize_all_keys(h)
  if h.is_a? Hash
    h.transform_keys!(&:to_sym)
    h.values.each do |val|
      val.each { |v| symbolize_all_keys(v) } if val.is_a? Array
      symbolize_all_keys(val)
    end
  end
  h
end

symbolize_all_keys(lib_data)

lib_data
#=> {:library=>[{:type=>"Books", :checkout=>false, :data=>[{:type=>"Books", :operator=>"AND", :details=>{:property=>"Name", :author=>"%s", :name=>"%s"}}, {:type=>"Books", :criteria=>{:property=>"Revision", :operator=>"%s", :value=>"%s"}}]}]}

对于第二部分,不清楚哪个值正在替换“%s”,具体取决于键。

只是一个想法,类似于上面的递归:

def replace_val(h, new_val = 'new_val')
  if h.is_a? Hash
    h.each do |key, val|
      h[key] = new_val if val == '%s'
      val.each { |v| replace_val(v) } if val.is_a? Array
      replace_val(val)
    end
  end
  h
end

replace_val(lib_data)

lib_data
#=> {:library=>[{:type=>"Books", :checkout=>false, :data=>[{:type=>"Books", :operator=>"AND", :details=>{:property=>"Name", :author=>"new_val", :name=>"new_val"}}, {:type=>"Books", :criteria=>{:property=>"Revision", :operator=>"new_val", :value=>"new_val"}}]}]}

在这里您可以访问值的键,但不能访问更高级别。

【讨论】:

  • 这对我有用,没有太多问题。非常感谢
【解决方案2】:

如果你使用的是rails,你可以使用HashWithIndifferentAccess

你也可以在 Rails 之外访问这个类,需要核心扩展:

require "active_support/core_ext/hash/indifferent_access"

2.6.5 :015 > lib_data = {'library'=>[{"type"=>"Books",
2.6.5 :016 >           "checkout"=>false, "data"=>[{"type"=>"Books", "operator"=>"AND", "details"=>{"property"=>"Name", "author"=>"%s",
2.6.5 :017 >                 "name"=>"%s"}}, {"type"=>"Books", "criteria"=>{"property"=>"Revision", "operator"=>"%s",
2.6.5 :018 >                 "value"=>"%s"}}]}]}
 => {"library"=>[{"type"=>"Books", "checkout"=>false, "data"=>[{"type"=>"Books", "operator"=>"AND", "details"=>{"property"=>"Name", "author"=>"%s", "name"=>"%s"}}, {"type"=>"Books", "criteria"=>{"property"=>"Revision", "operator"=>"%s", "value"=>"%s"}}]}]}
2.6.5 :019 > lib_data[:library]
 => nil
2.6.5 :020 > lib_data = lib_data.with_indifferent_access
 => {"library"=>[{"type"=>"Books", "checkout"=>false, "data"=>[{"type"=>"Books", "operator"=>"AND", "details"=>{"property"=>"Name", "author"=>"%s", "name"=>"%s"}}, {"type"=>"Books", "criteria"=>{"property"=>"Revision", "operator"=>"%s", "value"=>"%s"}}]}]}
2.6.5 :021 > lib_data[:library]
 => [{"type"=>"Books", "checkout"=>false, "data"=>[{"type"=>"Books", "operator"=>"AND", "details"=>{"property"=>"Name", "author"=>"%s", "name"=>"%s"}}, {"type"=>"Books", "criteria"=>{"property"=>"Revision", "operator"=>"%s", "value"=>"%s"}}]}]

【讨论】:

    猜你喜欢
    • 2014-05-19
    • 2016-09-04
    • 1970-01-01
    • 2011-08-15
    • 2012-10-27
    • 2015-02-03
    • 2015-04-21
    • 2012-08-03
    • 2018-12-07
    相关资源
    最近更新 更多