Domanda

Ho una serie di array che assomiglia a questo:

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

Ho anche un metodo che voglio invocare su ogni elemento dell'array:

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

Mi piacerebbe davvero poter dire qualcosa del tipo:

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

Esiste un modo per riuscirci senza dover modificare ogni elemento dell'array (ad esempio, scorrendo attraverso di esso e aggiungendo in qualche modo i simboli)? Oppure, se è troppo difficile, esiste un'alternativa migliore?

È stato utile?

Soluzione

La risposta migliore non è affatto usare un array, ma usare un hash:

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

Altri suggerimenti

Senza modificare affatto la struttura dei dati, è possibile modificare gli argomenti del blocco per ottenere la stessa cosa:

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

Funziona perché Ruby espande automaticamente le matrici interne ([" apple " ;, 100], ecc.) nell'elenco degli argomenti per il blocco ('do | name, calories | ... end'). Questo è un trucco che Ruby ha ereditato da Lisp, noto come "argomenti destrutturanti".

La risposta di Pesto (usa un hash) è buona, ma penso che preferirei usare 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)}

Questo si presta anche a cambiare mangia dall'assumere sia il nome che le calorie, a prendere un'istanza di frutta:

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

C'è qualche motivo per cui deve essere di per sé un array? Sembra che si tratti di un hash o di una lezione per Fruit.

Un array è sempre indicizzato da numeri, quindi per quanto ne so usare l'array standard non è possibile.

Personalmente opterei per l'utilizzo di un commento sopra il codice per suggerire che cosa f [0] e f [1] rappresenta.

Ma se sei intenzionato a farlo, immagino che alcuni tipi di anatre sui lavori della classe Array:


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) }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top