[英]Convert nested HashWithIndifferentAccess to nested Hash
Is there a nice way to transform an instance of a HashWithIndifferentAccess
(with nested instances of class HashWithIndifferentAccess
) to an instance of a Hash (with nested instances of class Hash
)?有没有一种很好的方法可以将 HashWithIndifferentAccess 的实例(具有
HashWithIndifferentAccess
HashWithIndifferentAccess
的嵌套实例)转换为 Hash 的实例(具有 class Hash
的嵌套实例)?
It seems easy to convert a nested Hash
to a nested HashWithIndifferentAccess
.将嵌套的
HashWithIndifferentAccess
转换为嵌套的Hash
似乎很容易。 Just use the with_indifferent_access
method that ActiveSupport provides.只需使用 ActiveSupport 提供的
with_indifferent_access
方法即可。 This converts all hashes, no matter how deeply nested.这会转换所有哈希,无论嵌套有多深。
hash = { late: { package: 2, trial: 100, penalty: { amount: 1 } },
no_show: { package: 1, trial: 100, penalty: { amount: 2 } } }
hash_wid = hash.with_indifferent_access
hash_wid.class
# ActiveSupport::HashWithIndifferentAccess #great
hash_wid [:no_show][:penalty].class
# ActiveSupport::HashWithIndifferentAccess #great
The reverse seems not so easy:反过来似乎并不那么容易:
hash = hash_wid.to_h
hash.class
# Hash # OK
hash[:no_show][:penalty].class
# ActiveSupport::HashWithIndifferentAccess # want this to be Hash
Hash#to_h
method only converts the top level hash, not the nested hashes. Hash#to_h
方法只转换顶级 hash,而不是嵌套的哈希值。
I tried the (Rails/ActiveSupport) deep_transform_values!
我尝试了 (Rails/ActiveSupport)
deep_transform_values!
method that extends the Hash
class:扩展
Hash
class 的方法:
hash_wid.deep_transform_values! do |value|
value.class == HashWithIndifferentAccess ? value.to_h : value
end
hash_wid.class
# ActiveSupport::HashWithIndifferentAccess # want this to be Hash
hash_wid[:no_show][:penalty].class
# ActiveSupport::HashWithIndifferentAccess # want this to be Hash
But looking to the source code of the deep_transform_values!
但是要查看
deep_transform_values!
method (and transform_values!
method that it depends upon), these can transform hashes of class Hash
, but not hashes of class HashWithIndifferentAccess
.方法(及其依赖的
transform_values!
方法),这些可以转换 class Hash
的哈希值,但不能转换 class HashWithIndifferentAccess
的哈希值。
So is there a nice way to transform a nested HashWithIndifferentAccess
to a nested Hash
?那么有没有一种很好的方法可以将嵌套的
HashWithIndifferentAccess
转换为嵌套的Hash
?
Thanks谢谢
Daniel丹尼尔
Your example indicates that you are using keys and values whose types are compatible with JSON. If your hash can be converted to JSON then a simple way to do it is:您的示例表明您使用的键和值的类型与 JSON 兼容。如果您的 hash 可以转换为 JSON,那么一种简单的方法是:
hash = JSON.load(JSON.dump({ foo: { bar: 'baz' }.with_indifferent_access }.with_indifferent_access))
=> {"foo"=>{"bar"=>"baz"}}
hash.class
=> Hash
hash['foo'].class
=> Hash
deep_transform_values
won't work in your case because of how that method is written :由于该方法的编写方式,
deep_transform_values
在您的情况下不起作用:
def _deep_transform_values_in_object(object, &block)
case object
when Hash
object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
when Array
object.map { |e| _deep_transform_values_in_object(e, &block) }
else
yield(object)
end
end
If your object is a Hash (or Array) then the method calls itself recursively until it finds a non-Hash and non-Array value onto which it can apply the transformation.如果您的 object 是一个 Hash(或数组),那么该方法会递归调用自身,直到它找到一个可以应用转换的非哈希和非数组值。 It should be pretty trivial to write your own implementation using that example though:
不过,使用该示例编写自己的实现应该是非常简单的:
def _deep_transform_values_in_object(object, &block)
case object
when Hash
# something less ugly than but similar to this
object = object.to_h if object.is_a?(ActiveSupport::HashWithIndifferentAccess)
object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
when Array
object.map { |e| _deep_transform_values_in_object(e, &block) }
else
yield(object)
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.