【问题标题】:Add an 'each' like method to a Ruby class that inherits from Hash向继承自 Hash 的 Ruby 类添加类似“每个”的方法
【发布时间】:2014-02-08 18:47:20
【问题描述】:

我想创建一个行为类似于标准 Ruby 哈希的类,并添加一些额外的访问方法。例如,给定:

class SpecificHash < Hash
  def initialize 
    (1..20).each do |num|
      self[num] = "value #{num.to_s}"
    end
  end
end

我可以通过标准的each 调用获得所有键值对的完整列表:

sh = SpecificHash.new
sh.each { |k,v| puts k } 

我有几件事想做。使用一个简化的示例,我将如何为 odd_keys 方法创建定义让我调用:

sh = SpecificHash.new
sh.odd_keys { |k,v| puts k }

让它像each 方法一样工作,但只包含键为奇数的键/值对?

【问题讨论】:

    标签: ruby hash


    【解决方案1】:

    将此方法添加到您的类应该可以工作:

    def odd
      return enum_for(:odd) unless block_given?
      each do |k, v|
        if k.respond_to?(:odd?) && k.odd?
          yield k, v
        end
      end
    end
    

    第一行是非常标准的做法,如果没有将块传递给您的方法,则允许您返回一个枚举器,就像each 所做的那样。它可以实现以下功能:

    hash.odd.select { ... }
    

    【讨论】:

    • 是的,这是一个更好的答案!
    • 我意识到“奇怪?”是一种检查整数是否为奇数的方法。我已更新问题以将示例方法重命名为“odd_keys”以区分两者。唯一需要更改的是def odddef odd_keysreturn enum_for(:odd) unless block_given?return enum_for(:odd_keys) unless block_given?hash.odd.select { ... }hash.odd_keys.select { ... } 是否正确?
    • 是的,听起来您正确识别了方法名称出现在我的答案中的三个位置,您需要更改所有这些位置。
    【解决方案2】:

    我相信这样的事情:

    class SpecificHash < Hash
      def odd
        each do |k, v|
          yield(k, v) if k.odd?
        end
      end
    end
    

    【讨论】:

      【解决方案3】:

      我看不出为您的用例定义类的目的。单个枚举器实例似乎足以满足您的目的。

      sh = (1..20).lazy
      sh.map{|k| [k, "value #{k}"]}.to_h # => ...
      sh.each{|k| puts k} # => ...
      sh.select(&:odd?).each{|k| puts k} # => ...
      

      【讨论】:

      • 我应该更清楚的是,具体的用例只是一个例子。我真正在寻找的是基于过滤从哈希生成“每个”类型输出的技术。例如,一个包含按 ID 索引的人员列表的哈希,我想在其中进行方法调用以根据每个人的属性返回不同的子集。我试图简化示例,但可能有点过火了。
      • 不过,最好使用惰性枚举器。您可以从散列或数组中创建一个惰性枚举器。它允许您添加一系列方法来创建“子集”,而无需创建中间数组/散列,因此非常高效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-25
      • 2022-09-23
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 2020-07-13
      相关资源
      最近更新 更多