ruby on rails - Cómo eliminar claves anidadas de una lista de hash en Rails
ruby-on-rails nested (3)
qué pasa
Hash[nested_hash.map {|k,v| [k,(v.respond_to?(:except)?v.except("nested_key2"):v)] }]
=> {"key1"=>"value1", "key2"=>{"nested_key1"=>"nestedvalue1"}}
ugh.
Ahora estoy intentando durante algunas horas eliminar una clave hash anidada de una lista hash. Vi muchas soluciones hashs no anidadas que se ve así:
sample_hash = {"key1" => "value1", "key2" => "value2"}
sample_hash.except("key1")
Esto resulta en:
{"key2"=>"value2"}
Pero si trato de usar el método except en un hash con clave anidada, entonces no funciona. Aquí mi código:
nested_hash = {"key1"=>"value1", "key2"=>{
"nested_key1"=>"nestedvalue1",
"nested_key2"=>"nestedvalue2"
}
}
nested_hash.except("nested_key2")
El método except () devuelve el nested_hash sin ningún cambio. He buscado una solución sobre cómo puedo pasar las claves hash anidadas al método except, pero no pude encontrar nada. ¿Es posible pasar claves anidadas a este método o debería usar algún otro método que elimine una clave hash anidada de mi lista hash?
tratar
my_hash = Hash[nested_hash.map {|k,v| {k=>v.is_a? Array ? v.except("nested_key2") : v}}.map {|key, value| [key, value]}]
Pero esto parece retrasado, ojalá nunca comencé en este camino, estoy dispuesto a apostar que hay una manera más fácil.
La solución aceptada es válida para el escenario dado, pero si está buscando algo que haga esto para tablas hash anidadas arbitrariamente, entonces necesitará una solución recursiva. No pude encontrar una solución adecuada en ningún lado, así que escribí una aquí .
Reproducido aquí con anotaciones:
class Hash
def except_nested(key)
r = Marshal.load(Marshal.dump(self)) # deep copy the hashtable
r.except_nested!(key)
end
def except_nested!(key)
self.except!(key)
self.each do |_, v| # essentially dfs traversal calling except!
v.except_nested!(key) if v.is_a?(Hash)
end
end
end
agregándolo a la clase Hash
para que pueda llamarlo de la misma manera que llama excepto / ¡excepto! en cualquier otro lugar.
t = { a: ''1'', b: { c: ''3'', d: ''4'' } }
r = t.except_nested(:c)
# r => {:a=>"1", :b=>{:d=>"4"}}
# t => {:a=>"1", :b=>{:c=>"3", :d=>"4"}}
t.except_nested!(:c)
# t => {:a=>"1", :b=>{:d=>"4"}}