3

我有一个哈希数组

例如:

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' 

我想知道是否有类似的快捷方式来执行上述操作。

4

5 回答 5

6

I believe your current code cars.collect{|c| c[:company]} is the best way if you're enumerating over an arbitrary array. The method you would pass in via the & shortcut would have to be a method defined on Hash since each object in the array is of type Hash. Since there is no company method defined for Hash you get the "undefined method 'company'" error.

You could use cars.collect(&:company) if you were operating on an Array of Cars though, because each object passed into the collect block would be of type Car (which has the company method available). So maybe you could modify your code so that you use an array of Cars instead.

于 2011-03-29T13:39:40.563 回答
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"]
于 2011-03-29T14:26:03.217 回答
0

另一个你不应该真正使用的可怕猴子补丁:

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)
于 2011-03-29T22:26:00.970 回答
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

注意:我不是建议这样做,我只是说这是可能的。

于 2011-03-29T14:05:03.363 回答
0

在您的情况下无法使用,因为在 collect 中您使用方法[]和参数:company。构造 &:company 接受标签:company并转换为Proc,所以它只有一个参数 - 方法的名称。

于 2011-03-29T14:01:17.943 回答