关于Ruby收集方法的问题

发布于 2024-10-27 21:12:36 字数 476 浏览 6 评论 0原文

我有一个哈希数组

例如:

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' 

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

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' 

I was wondering if there is a similar shortcut to perform the above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

﹎☆浅夏丿初晴 2024-11-03 21:12:36

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

如果您正在操作汽车数组,则可以使用cars.collect(&:company),因为传递到collect块的每个对象的类型都是< code>Car (其中有可用的公司方法)。因此,也许您可​​以修改代码,以便使用汽车数组。

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.

八巷 2024-11-03 21:12:36

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

You could convert the hashes to 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"]
围归者 2024-11-03 21:12:36

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

It's impossible to use in your case, because in collect you use method [] and argument :company. The construction &:company takes labels :company and converts to Proc, so it's only one argument - the name of method.

时光磨忆 2024-11-03 21:12:36

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

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

Unfortunately Ruby hashes can't do that. Clojure maps on the other hand have functions for each key which return the corresponding value, which would be easy enough to do if you are so inclined (you should also add the corresponding respond_to? method):

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

Note: I'm not advising this, I'm just saying it's possible.

冷…雨湿花 2024-11-03 21:12:36

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

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)

Another horrible monkeypatch you shouldn't really use:

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文