2013-05-28 18 views
5

Ora sto provando per alcune ore a rimuovere una chiave hash nidificata di un elenco hash. Ho visto molti soluzione non annidata hashs Wich si presenta così:Come rimuovere le chiavi annidate da un elenco hash in Rails

sample_hash = {"key1" => "value1", "key2" => "value2"} 
    sample_hash.except("key1") 

Questo si traduce in:

{"key2"=>"value2"} 

Ma se provo ad usare l'eccezione di metodo su un hash con chiave nidificato allora doesn lavorare Ecco il mio codice:

nested_hash = {"key1"=>"value1", "key2"=>{ 
              "nested_key1"=>"nestedvalue1", 
              "nested_key2"=>"nestedvalue2" 
              } 
       } 

    nested_hash.except("nested_key2") 

L'eccezione() restituisce il nested_hash senza alcuna modifica. Ho cercato una soluzione su come posso passare le chiavi hash annidate al metodo except, ma non ho trovato nulla. È persino possibile passare le chiavi nidificate a questo metodo o dovrei usare qualche altro metodo che cancella una chiave hash nidificata dal mio elenco hash?

+1

Forse vuoi un vero albero, piuttosto che un hash annidato. Potresti consultare https://github.com/evolve75/RubyTree, https://github.com/stefankroes/ancestry o https://github.com/mceachen/closure_tree per le gemme che potrebbero funzionare per te. –

risposta

8

che dire

Hash[nested_hash.map {|k,v| [k,(v.respond_to?(:except)?v.except("nested_key2"):v)] }] 

=> {"key1"=>"value1", "key2"=>{"nested_key1"=>"nestedvalue1"}} 

ugh.

+0

Funziona! Molte grazie è quello che ho cercato. – user1367922

+0

Funziona alla grande, ma potresti spiegare questa notazione? In che modo la parola chiave "Hash" prende in un indice di array e perché stiamo mappando ciascun elemento su un array di [k, v] o [k, v.except ("nested_key2")]? –

+0

vedere http://www.ruby-doc.org/core-2.0/Hash.html#method-c-5B-5D, il metodo standard per creare gli hash. Accetta o un elenco di chiave, valore, chiave, valore, ... o chiave di associazione => valore, chiave => valore, ... o matrice nidificata, ciò che usiamo qui. –

0

provare

my_hash = Hash[nested_hash.map {|k,v| {k=>v.is_a? Array ? v.except("nested_key2") : v}}.map {|key, value| [key, value]}] 

ma questo sembra ritardato, vorrei che non ho mai iniziato su questa strada, io sono pronto a scommettere c'è un modo più semplice!

+0

thx per il tuo suggerimento. ma genera un NoMethodError: metodo non definito 'tranne 'for" value1 ": String – user1367922

+0

I; ll aggiungi un'eccezione – RadBrad

0

La soluzione accettata è valida per lo scenario indicato, ma se stai cercando qualcosa che faccia questo per le tabelle hash nidificate arbitrariamente, avrai bisogno di una soluzione ricorsiva. Non sono riuscito a trovare una soluzione adatta da nessuna parte, quindi ne ho scritto uno here.

qui riprodotto con annotazioni:

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 

aggiungerlo alla classe Hash in modo che si può chiamare allo stesso modo si chiama salvo/salvo! da qualsiasi altra parte.

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