Pregunta

La creación de hashes de hashes en Ruby permite realizar búsquedas bidimensionales convenientes (o más). Sin embargo, al insertar uno, siempre se debe verificar si el primer índice ya existe en el hash. Por ejemplo:

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

Sería preferible hacer lo siguiente cuando el nuevo Hash se crea automáticamente:

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

De manera similar, cuando se busca un valor donde el primer índice no existe, sería preferible que se devuelva nil en lugar de recibir un método indefinido para el error '[]'.

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

Uno podría crear una clase de Hash wrapper que tenga este comportamiento, pero ¿existe un idioma de Ruby para realizar esta tarea?

¿Fue útil?

Solución

Puede pasar el Hash.new funciona un bloque que se ejecuta para generar un valor predeterminado en caso de que el valor consultado aún no exista:

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

Por supuesto, esto se puede hacer recursivamente.

/ EDIT: Wow, hay un artículo respondiendo a esta pregunta.

En aras de la integridad, aquí está la solución del artículo para hashes de profundidad arbitrarios:

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

Los créditos van a Kent desde Data Noise .

Otros consejos

La autovivificación, como se llama, es tanto una bendición como una maldición. El problema puede ser que si " aspecto " a un valor antes de que esté definido, te quedas con este hash vacío en la ranura y necesitarás podarlo más tarde.

Si no le importa un poco de anarquía, siempre puede bloquear las declaraciones de estilo igual o igual que le permitirá construir la estructura esperada a medida que la consulta:

((h ||= { })['w'] ||= { })['z']
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top