【问题标题】:How to define a method to_proc in Array so I can use it in a particular situations如何在 Array 中定义一个 to_proc 方法,以便我可以在特定情况下使用它
【发布时间】:2013-12-05 21:22:26
【问题描述】:

假设我有课:

class Car
  attr_accessor :brand, :color
  def initialize(br, col)
    @brand = br
    @color = col 
  end
end

first_car = Car.new 'Mercedes', 'Yellow'
second_car = Car.new 'Jaguar', 'Orange'
third_car = Car.new 'Bentley', 'Pink'

array_of_cars = [first_car, second_car]

所以,我们的想法是在类 Array 中定义一个方法 to_proc,这样就可以发生这种情况:

array_of_cars.map(&[:brand, :color]) #=> [['Mercedes', 'Yellow'], ['Jaguar', 'Orange'], ['Bentley', 'Pink']]

或者我怎么能以某种方式做这样的事情:

[:brand, :color].to_proc.call(first_car) #=> ['Mercedes', 'Yellow']

【问题讨论】:

  • 您想在您的to_proc 实现中硬编码&[:brand, :color] 吗?
  • 好吧,如果我能动态地做到这一点,不管对象是什么,那就太好了,但如果你有想法,我会很高兴看到它。

标签: ruby overriding proc


【解决方案1】:

标准的Symbol#to_proc 或多或少是一个e.send(self) 调用,而您只想send 为每个元素提供一个充满符号的数组,所以只需用这样的方式准确地说出来:

class Array
  def to_proc
    proc { |e| self.map { |m| e.send(m) } }
  end
end

我可能不会为此修补 Array,如果我想要更易于阅读的内容,我只会使用本地 lambda:

brand_and_color = lambda { |e| [:brand, :color].map { |s| e.send(s) } }
array_of_cars.map(&brand_and_color)

【讨论】:

  • 我是 ruby​​ 的新手,有很多我不熟悉的东西。在您的示例中,如果我在每次迭代中都有 [first_car, second_car].map(&[:brand, :color]) 什么是“e”、“self”和“m”。我有点困惑。
  • self 将是数组本身(即[:brand, :color]),e 将是发送到 proc 的 array_of_cars 的元素,m 将是元素self 的(即要调用的方法)。 map 文档可能值得一读。
  • 如果我没记错调用这个补丁 to_proc 会返回一个 proc 对象而不是一个数组?
  • @JasdeepSingh: 是的,如果to_proc 没有返回一个proc,那么&array 将只是引发TypeError 的一种奇特方式。
  • @muistooshort 哈哈哈,哈哈 明白了。是的,我觉得很奇怪为什么该方法必须专门称为to_proc
【解决方案2】:
class Array

  def to_proc(arr)
    self.map do |elem|
       arr.map { |attr| elem.send(attr) }
    end
  end

end

就像提到的mu is too short,我不会像这样修补Array

但是,这将为您完成工作。

这样调用它:

array_of_cars.to_proc([:brand, :color])

【讨论】:

    【解决方案3】:

    也许使用正常的方法?

    module ConvertInstanceToHash
    
      def to_proc(obj, keys)
        hash = {}
        obj.instance_variables.each {|var| hash[var.to_s.delete("@")] = obj.instance_variable_get(var)}
        hash = hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
        hash.values_at(*keys).compact
      end
    
    end
    
    irb(main):009:0> first_car = Car.new 'Mercedes', 'Yellow'
    => #<Car:0x000000045fb870 @brand="Mercedes", @color="Yellow">
    irb(main):010:0> to_proc(first_car, [:brand, :color])
    => ["Mercedes", "Yellow"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-03
      • 2021-01-06
      • 2011-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多