2009-11-06 17 views
6

Por razones de conveniencia estoy tratando de asignar valores múltiples a una clave hash en Ruby. Aquí está el código hasta ahora¿Cómo puedo asignar múltiples valores a una clave hash?

myhash = { :name => ["Tom" , "Dick" , "Harry"] } 

bucle a través del hash da una cadena concatenada de los 3 valores

Salida:

name : TomDickHarry 

salida requerida:

:name => "Tom" , :name => "Dick" , :name => "Harry" 

¿Qué código debe ¿Escribo para obtener la salida requerida?

Respuesta

4

Has creado un hash con el nombre del símbolo como la clave y una matriz con tres elementos como valor, por lo que necesitarás recorrer el myhash[:name] para obtener los elementos individuales de la matriz.

6
myhash.each_pair {|k,v| v.each {|n| puts "#{k} => #{n}"}} 
#name => Tom 
#name => Dick 
#name => Harry 

El formato de salida no es exactamente lo que necesita, pero creo que tiene la idea.

+0

@pierr, gracias. Tengo más de 1 clave en ese hash y quiero iterar sobre claves selectivas, para eso estoy intentando Hash [* myhash.select {| k, v | [: name] .include? (k)}. flatten], pero al obtener un error, ¿qué estoy haciendo mal? –

+0

El motivo del error es que aplanar es recursivo, por lo que se obtiene una lista larga y no una lista de pares de claves y valores. – mikej

5

Las respuestas de Rohith y pierr están bien en este caso. Sin embargo, si esto es algo que va a hacer un uso extensivo, vale la pena saber que la estructura de datos que se comporta como un Hash pero permite múltiples valores para una clave se conoce generalmente como multimap. Hay un par de implementaciones de esto para Ruby incluyendo this one.

+0

El enlace está muerto: http://github.com/josh/multimap – wisbucky

3

re: el problema de iterar sobre claves selectivas. Intente usar reject con la condición invertida en lugar de usar select.

p. Ej. da:

{:name=>["Tom", "Dick", "Harry"], :keep=>[4, 5, 6], :discard=>[1, 2, 3]} 

donde queremos :name y :keep pero no :discard

con select:

myhash.select { |k, v| [:name, :keep].include?(k) } 
=> [[:name, ["Tom", "Dick", "Harry"]], [:keep, [4, 5, 6]]] 

El resultado es una lista de pares.

pero con reject:

myhash.reject { |k, v| ![:name, :keep].include?(k) } 
=> {:name=>["Tom", "Dick", "Harry"], :keep=>[4, 5, 6]} 

El resultado es un hash con sólo las entradas que desee.

Esto se puede combinar con la respuesta de pierr:

hash_to_use = myhash.reject { |k, v| ![:name, :keep].include?(k) } 
hash_to_use.each_pair {|k,v| v.each {|n| puts "#{k} => #{n}"}} 
Cuestiones relacionadas