Ruby collect方法相关问题

3

I have an array of hashes

Eg:

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' 

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

我不认为那是懒惰的,那是简洁的。 - B Seven
5个回答

6
我认为如果你正在枚举一个任意数组,那么你当前的代码 cars.collect{|c| c[:company]} 是最好的方法。通过 & 快捷方式传递的方法必须是在哈希上定义的方法,因为数组中的每个对象都是类型为 Hash 的。由于没有为 Hash 定义 company 方法,所以会出现 "undefined method 'company'" 错误。
但是,如果你操作的是 Cars 数组,则可以使用 cars.collect(&:company),因为传入 collect 块的每个对象都是类型为 Car 的(它具有可用的 company 方法)。因此,也许你可以修改你的代码,使用 Cars 数组。

是的,那很有道理。这也是我最初的想法。谢谢! - Punit Rathore

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"]

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

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

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)

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接