关于Ruby收集方法的问题

时间:2011-03-29 13:30:50

标签: ruby collect

我有一系列哈希

例如:

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 个答案:

答案 0 :(得分:6)

我相信如果您对任意数组进行枚举,那么当前代码cars.collect{|c| c[:company]}是最好的方法。你将通过& amp;快捷方式必须是在Hash上定义的方法,因为数组中的每个对象都是Hash类型。由于没有为company定义Hash方法,因此您会收到“未定义方法'公司'”错误。

如果你在汽车数组上运行,你可以使用cars.collect(&:company),因为传递到collect块的每个对象都是Car类型(公司方法可用) )。所以也许你可以修改你的代码,以便你使用一系列的汽车。

答案 1 :(得分:5)

您可以将哈希值转换为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"]

答案 2 :(得分:0)

在你的情况下不可能使用,因为在收集中你使用方法[]和参数:公司。构造&公司采用标签:company并转换为Proc,因此它只是一个参数 - 方法的名称。

答案 3 :(得分:0)

不幸的是,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

注意:我不是在告诉我,我只是说这是可能的。

答案 4 :(得分:0)

另一个你不应该使用的可怕的monkeypatch:

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)