Вопрос о методе сбора Ruby - PullRequest
3 голосов
/ 29 марта 2011

у меня есть массив хэшей

Например:

cars = [{:company => "Ford", :type => "SUV"},
        {:company => "Honda", :type => "Sedan"},
        {:company => "Toyota", :type => "Sedan"}]

# i want to fetch all the companies of the cars
cars.collect{|c| c[:company]}
# => ["Ford", "Honda", "Toyota"] 

# i'm lazy and i want to do something like this
cars.collect(&:company)
# => undefined method `company' 

Мне было интересно, есть ли подобный ярлык для выполнения вышеуказанного.

Ответы [ 5 ]

6 голосов
/ 29 марта 2011

Я считаю, что ваш текущий код cars.collect{|c| c[:company]} - лучший способ, если вы перечисляете произвольный массив.Метод, который вы передадите через ярлык &, должен быть методом, определенным в Hash, поскольку каждый объект в массиве имеет тип Hash.Поскольку для Hash не определен метод company, вы получите ошибку «undefined method 'company'".

Вы можете использовать cars.collect(&:company), если вы работаете с Массивом Автомобилей, потому что каждый объект, переданный в блок collect, будет иметь тип Car (для которого доступен метод компании).Поэтому, возможно, вы могли бы изменить свой код, чтобы вместо него использовать массив Cars.

5 голосов
/ 29 марта 2011

Вы можете конвертировать хеши в OpenStructs.

require 'ostruct'
cars = [{:company => "Ford", :type => "SUV"},
        {:company => "Honda", :type => "Sedan"},
        {:company => "Toyota", :type => "Sedan"}]
cars = cars.map{|car| OpenStruct.new(car)}

p cars.map( &:company )
#=> ["Ford", "Honda", "Toyota"]
0 голосов
/ 30 марта 2011

Еще одна ужасная обезьяна, которую вы не должны использовать:

class Symbol
  def to_proc
    if self.to_s =~ /bracket_(.*)/
      Proc.new {|x| x[$1.to_sym]}
    else
      Proc.new {|x| x.send(self)}
    end
  end
end

cars = [{:company => "Ford", :type => "SUV"},
        {:company => "Honda", :type => "Sedan"},
        {:company => "Toyota", :type => "Sedan"}]

cars.collect(&:bracket_company)
0 голосов
/ 29 марта 2011

К сожалению, хэши Ruby не могут этого сделать.Карты Clojure, с другой стороны, имеют функции для каждой клавиши, которые возвращают соответствующее значение, что было бы достаточно легко сделать, если вы склонны (вы также должны добавить соответствующий метод respond_to?):

>> class Hash
..   def method_missing(m)
..     self.has_key?(m) ? self[m] : super
..     end
..   end #=> nil
>> cars.collect(&:company) #=> ["Ford", "Honda", "Toyota"]
>> cars.collect(&:compay)
NoMethodError: undefined method `compay' for {:type=>"SUV", :company=>"Ford"}:Hash

Примечание: я не советую это, я просто говорю, что это возможно.

0 голосов
/ 29 марта 2011

Невозможно использовать в вашем случае, потому что при сборе вы используете метод [] и аргумент: компания.Конструкция &: компания принимает метки :company и преобразует их в Proc, поэтому это только один аргумент - имя метода.

...