Crear hash a partir de una matriz de nombres y variables (no se puede convertir una matriz en una cadena)

Quiero construir una matriz anidada de hashes. tengo una matriz, branch, que se ve así:

branch = ["handbags", "womens-shoes", "womens-beauty", "womens-clothes"]

Luego tengo otra matriz que contiene cosas que van con handbags:

handbags = ["wallets", "backpacks", "clutches", "evening-handbags", "hobo-bags", "satchels", "shoulder-bags", "tote-bags"]

Quiero insertar, en un bucle, el handbags matriz en el branch matriz, de modo que obtengo algo como esto:

branch = {"handbags" => ["wallets", "backpacks", "clutches", "evening-handbags", "hobo-bags", "satchels", "shoulder-bags", "tote-bags"], "womens-shoes"],...}

Lo intento así:

def insert_branch(branch, branch_index, candidate, candidate_index)
    branch[[branch_index], branch[branch_index]] ||= {}
    branch[[branch_index], branch[branch_index]] = candidate[candidate_index]  
end

dónde

candidate[candidate_index] = ["wallets", "backpacks", "clutches", "evening-handbags", "hobo-bags", "satchels", "shoulder-bags", "tote-bags"]

me da

no se puede convertir Array en Entero

¿Cómo puedo lograr esto?

preguntado el 03 de mayo de 12 a las 17:05

¿Por qué nos das todo ese código? nunca usas branch, handbags o el insert_branch. Además nunca defines candidate. -

No creo que una [matriz] pueda convertirse en una {matriz asociativa} como esa. Pero en realidad no conozco a Ruby, así que no deberías escucharme. -

6 Respuestas

No puede indexar una matriz con un objeto diferente a un número entero. Tienes que usar un hash. Como la rama es una matriz, Ruby espera que un Integer indexe cada elemento y, como le está dando otra matriz, intenta convertirlo en un Integer, lo que produce el error. Prueba esto:

branch = Hash.new #unnecessary, but makes the class explicit
handbags = ["wallets", "backpacks", "clutches", "evening-handbags", "hobo-bags", "satchels", "shoulder-bags", "tote-bags"]
branch["handbags"] = handbags

branch.inspect producirá:

"{\"handbags\"=>[\"wallets\", \"backpacks\", \"clutches\", \"evening-handbags\", \"hobo-bags\", \"satchels\", \"shoulder-bags\", \"tote-bags\"]}"

contestado el 03 de mayo de 12 a las 17:05

+1 por escribir sobre por qué lo que estaba haciendo el OP estaba mal y explicarlo. Sin embargo, a esta respuesta le falta lo que yo pensar fue la intención del OP de recorrer una serie de nombres y encontrar variables locales con el mismo nombre. - Phrogz

Si realmente tienes:

array = ["foo", "bar"]
foo   = ...
bar   = ...

entonces no tiene suerte: no puede (de ninguna manera) obtener el objeto al que hace referencia una variable local en función de su nombre. Cada vez que desee buscar un valor por nombre, debe usar un Hash para almacenar los valores para recuperarlos más tarde. es decir, debe cambiar sus estructuras de datos para que sean algo como:

array  = ["foo","bar"]
things = {
  "foo" => ...,
  "bar" => ...
}

... pero por supuesto entonces tú tienen tu respuesta sin necesidad de hacer más trabajo.

Si por alguna razón no puede cambiar su código para usar un solo literal Hash, pero puede cambiar su código para usar variables de instancia en lugar de variables locales, puede hacer esto:

array  = ["foo", "bar"]
@foo   = ...
@bar   = ...
branch = Hash[ array.map{ |name| [name,instance_variable_get("@#{name}")] } ]

El código anterior requiere Ruby 1.9; si en su lugar está usando el antiguo 1.8, dígalo.

Visto en acción:

irb(main):001:0> a = %w[foo bar jim]
#=> ["foo", "bar", "jim"]

irb(main):002:0> @foo = %w[ 1 2 3 ]
#=> ["1", "2", "3"]
irb(main):003:0> @bar = %w[ 4 5 6 ]
#=> ["4", "5", "6"]
irb(main):004:0> @jim = %w[ 7 8 9 ]
#=> ["7", "8", "9"]

irb(main):006:0> Hash[ a.map{ |name| [name,instance_variable_get("@#{name}")] } ]
#=> {"foo"=>["1", "2", "3"], "bar"=>["4", "5", "6"], "jim"=>["7", "8", "9"]}

contestado el 03 de mayo de 12 a las 18:05

gracias por tu completa respuesta Esta fue una decisión un poco difícil, pero le di esta a CodeGnome, solo porque era un poco más fácil de entender para mí. - Astuto

El rubí Clase de matriz dice:

Las matrices son colecciones ordenadas e indexadas por enteros de cualquier objeto.

entonces el problema es que su índice debe ser un número entero, pero está tratando de asignarlo a la matriz usando un índice de cadena. Puede considerar convertir todo en un hash (para que pueda usar cadenas como claves) o puede colocar un hash o sub-arreglo en el arreglo en el índice adecuado de la siguiente manera:

idx = branch.index "handbags"
branch[idx] = { "handbags" => handbags }

También debe echar un vistazo a Array#zip y ver si eso le proporcionará la funcionalidad que necesita.

contestado el 03 de mayo de 12 a las 17:05

gracias por la respuesta directa! Esto funcionó muy bien para mí. ¡Gracias! - Astuto

Tiene problemas de indexación en su código. La declaración:

branch[[branch_index], branch[branch_index]]

está siendo entendido por Ruby como tratando de acceder branch en el índice [branch_index] (que no es un índice válido... es una matriz) y mira branch[branch_index] muchos elementos (que tampoco es un número válido de elementos... es una cadena).

Creo que lo que realmente quieres aquí es:

def insert_branch(branch, branch_index, candidate, candidate_index)
    branch[branch_index] = {branch[branch_index] => candidate[candidate_index]}
end

contestado el 03 de mayo de 12 a las 17:05

Lo que tienes está un poco apagado. Quizás esto te sirva de orientación.

branch = ["handbags", "womens-shoes", "womens-beauty", "womens-clothes"]

handbags = ["wallets", "backpacks", "clutches", "evening-handbags", "hobo-bags", "satchels", "shoulder-bags", "tote-bags"]

def insert_branch(catagories,catagories_index,branch)
  catagories[catagories_index] = Hash[catagories[catagories_index],branch] 
end

insert_branch(branch,0,handbags)


>> p branch  # OUTPUT IS
>> [{"handbags"=>["wallets", "backpacks", "clutches", "evening-handbags", "hobo-bags", "satchels", "shoulder-bags", "tote-bags"]}, "womens-shoes", "womens-beauty", "womens-clothes"]

contestado el 03 de mayo de 12 a las 17:05

¡Gracias por tu respuesta slindsey3000! Su enfoque me parece bastante válido: le dio este a CodeGnome porque parecía más sencillo. - Astuto

Lo que estás tratando de hacer se puede hacer simplemente con:

a = %w|Things Animals Cities|
things = %w|Desk Table Lamp|

a[0] = {a[0] => things}

a
=> [{"Things"=>["Desk", "Table", "Lamp"]}, "Animals", "Cities"]

En tu caso, es

branch[0] = {branch[0] => handbags}

Edit: usando metaprogramación, puede buscar matrices en función de su nombre:

categories = %w|Things Animals Cities|
things = %w|Desk Table Lamp|
animals = %w|Dog Cat Turtle|
cities = %w|London Rome Madrid|

result = categories.map do |category| 
  { category => eval(category.downcase) }
end

result
=> [{"Things"=>["Desk", "Table", "Lamp"]},
    {"Animals"=>["Dog", "Cat", "Turtle"]},
    {"Cities"=>["London", "Rome", "Madrid"]}]

Tenga en cuenta el uso de eval para obtener el Array nombrado por la categoría como valor.

contestado el 03 de mayo de 12 a las 18:05

Creo que el OP está tratando de buscar el valor de la variable en función de la cadena en la matriz. - Phrogz

Gracias albomoriconi! Le agradezco su respuesta. Le di este a CodeGnome, pero creo que también tienes la esencia. - Astuto

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.