2008-10-04 11 views
34

La creazione di hash di hash in Ruby consente di ottenere due (o più) oculari dimensionale. Tuttavia, quando si inserisce uno deve sempre verificare se il primo indice esiste già nell'hash. Ad esempio:Hash of Hashes Idiom in Ruby?

h = Hash.new 
h['x'] = Hash.new if not h.key?('x') 
h['x']['y'] = value_to_insert 

Sarebbe preferibile effettuare le seguenti operazioni in cui il nuovo hash viene creato automaticamente:

h = Hash.new 
h['x']['y'] = value_to_insert 

Analogamente, quando si cerca un valore in cui il primo indice non esiste, sarebbe preferibile restituire nil anziché ricevere un metodo non definito per l'errore '[]'.

looked_up_value = h['w']['z'] 

Si potrebbe creare una classe wrapper Hash che ha questo comportamento, ma c'è un esistente un idioma rubino per realizzare questo compito?

+0

C'è un hash di idiomi hash che restituiscono 0 dopo una certa profondità? (Sto contando le cose e sto usando h [: foo] [: bar] [: baz] + = 1) –

risposta

54

È possibile passare la funzione Hash.new un blocco che viene eseguito per produrre un valore di default nel caso in cui il valore richiesto non esiste ancora:

h = Hash.new { |h, k| h[k] = Hash.new } 

Naturalmente, questo può essere fatto in modo ricorsivo.

/EDIT: Wow, c'è an article rispondere a questa stessa domanda.

Per ragioni di completezza, ecco la soluzione dal articolo per hash profondità arbitraria:

hash = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)})) 

crediti vanno a Kent Data Noise.

+1

Wow. È impressionante. –

+0

Collegamento guasto. Impressionante soluzione però. –

+1

Il link morto viene commutato qui http://inquirylabs.com/blog2009/2006/09/20/ruby-hashes-of-arbitrary-depth/ – Autodidact

4

L'autovivificazione, come viene chiamato, è sia una benedizione che una maledizione. Il problema può essere che se "guardi" un valore prima che sia definito, sei bloccato con questo hash vuoto nello slot e dovresti eliminarlo più tardi.

Se non ti dispiace un po 'di anarchia, si può sempre e solo di marmellata o-uguale dichiarazioni di stile che permetteranno di costruire la struttura prevista, come si esegue una query che:

((h ||= { })['w'] ||= { })['z']