ruby-on-rails hash nested key except

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