Рубин:Как мне использовать символы для представления объектов в массиве?

StackOverflow https://stackoverflow.com/questions/808069

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть массив массивов, который выглядит примерно так:

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

У меня также есть метод, который я хочу вызвать для каждого элемента массива:

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

Я бы очень хотел иметь возможность сказать что-то вроде:

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

Есть ли способ, которым я могу выполнить это без необходимости изменять каждый элемент в массиве (например, путем перебора его и каким-либо образом добавляя символы)?Или, если это слишком сложно, есть ли лучшая альтернатива?

Это было полезно?

Решение

Лучший ответ - вообще не использовать массив, а использовать хэш:

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

Другие советы

Вообще не меняя структуру данных, вы могли бы изменить аргументы блока, чтобы добиться того же самого:

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

Это работает, потому что Ruby автоматически расширит внутренние массивы (["apple", 100] и т.д.) В список аргументов для блока ('do |name, calories| ...конец").Это трюк, который Ruby унаследовал от Lisp, известный как "деструктурирующие аргументы".

Ответ Песто (использовать хэш) хороший, но я думаю, что предпочел бы использовать 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)}

Это также поддается изменению eat начиная с определения названия и калорийности и заканчивая приведением примера фрукта:

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

Есть ли какая-то причина для этого должен быть массивом как таковым?Это, кажется, кричит о том, что это хэш или класс для Фруктов.

Массив всегда индексируется числами, поэтому, насколько я знаю, используя стандартный массив, это невозможно.

Лично я бы просто предпочел использовать комментарий над кодом, чтобы намекнуть, что означают f [0] и f [1].

Но если вы одержимы идеей сделать это, я думаю, что некоторая утиная типизация в классе 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) }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top