Pregunta

Tengo una serie de matrices que se parecen a esto:

fruits_and_calories = [
  ["apple", 100],
  ["banana", 200],
  ["kumquat", 225],
  ["orange", 90]
]

También tengo un método que quiero invocar en cada elemento de la matriz:

fruits_and_calories.each do |f| eat(f[0], f[1])

Realmente me gustaría poder decir algo como:

fruits_and_calories.each do |f| eat(f[:name], f[:calories])

¿Hay alguna forma de poder hacer esto sin tener que cambiar cada elemento de la matriz (por ejemplo, al iterar a través de él y agregar los símbolos de alguna manera)? O, si eso es demasiado difícil, ¿hay alguna alternativa mejor?

¿Fue útil?

Solución

La mejor respuesta es no usar una matriz en absoluto, sino usar un hash:

fruits_and_calories = { :apple => 100,
                        :banana => 200,
                        :kumquat => 225,
                        :orange => 90}
fruits_and_calories.each do |name, calories| 
  eat(name, calories)
end

Otros consejos

Sin cambiar la estructura de datos, podría cambiar los argumentos de bloque para lograr lo mismo:

fruits_and_calories.each  do |name, calories|  eat(name, calories);  end

Esto funciona porque Ruby expandirá automáticamente las matrices internas ([" apple " ;, 100], etc.) en la lista de argumentos para el bloque ('do | name, calorías | ... end'). Este es un truco que Ruby heredó de Lisp, conocido como 'desestructuración de argumentos'.

La respuesta de Pesto (usar un hash) es buena, pero creo que preferiría usar un Struct.

Fruit = Struct.new(:name, :calories)

fruits = [
  Fruit.new("apple", 100),
  Fruit.new("banana", 200),
  Fruit.new("kumquat", 225),
  Fruit.new("orange", 90)
]

fruits.each {|f| eat(f.name, f.calories)}

Esto también se presta al cambio de eat de tomar tanto el nombre como las calorías, a tomar una instancia de fruta:

fruits.each {|f| eat(f)}

¿Hay alguna razón por la que debe ser una matriz, per se? Eso parece ser un hash, o una clase para Fruit.

Una matriz siempre se indexa por números, por lo que sé que usar la matriz estándar no es posible.

Personalmente, solo optaría por usar un comentario sobre el código para sugerir qué significan f [0] yf [1].

Pero si estás empeñado en hacerlo, supongo que algunos tipos de pato en la clase Array funcionan:


class Array
  def name ; self[0] ; end
  def calories ; self[1] ; end
end

# then call it with:
fruits_and_calories.each {|f| eat(f.name, f.calories) }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top