【问题标题】:Question on Ruby collect method关于 Ruby 收集方法的问题
【发布时间】:2011-07-25 07:19:25
【问题描述】:

我有一个哈希数组

例如:

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' 

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

【问题讨论】:

  • 我不认为这很懒惰。很简洁。

标签: ruby collect


【解决方案1】:

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

如果你在汽车数组上操作,你可以使用cars.collect(&:company),因为传入collect块的每个对象都是Car类型(它有公司方法可用)。因此,也许您可​​以修改您的代码,以便使用 Cars 数组。

【讨论】:

  • 是的,这是有道理的。这也是我最初的想法。谢谢!
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-10-26
          • 1970-01-01
          • 2018-05-14
          • 1970-01-01
          • 2017-01-29
          • 2016-01-05
          • 1970-01-01
          • 2011-05-05
          相关资源
          最近更新 更多