如何在 Ruby 中实现查找类?

Posted

技术标签:

【中文标题】如何在 Ruby 中实现查找类?【英文标题】:How to implement a lookup class in Ruby? 【发布时间】:2014-12-07 02:45:01 【问题描述】:

我有一个不可变值对象的列表。查找类提供了迭代和查询数据的方法:

class Banker
  Bank = Struct.new(:name, :bic, :codes)

  attr_reader :banks
  def initialize
    @banks = [
      Bank.new('Citibank',    '1234567', ['1', '2']),
      Bank.new('Wells Fargo', '7654321', ['4']), # etc.
    ]
  end

  def find_by_bic(bic)
    banks.each do |bank|
      return bank if bank.bic == bic
    end
  end
end

@banks 在每次使用 Banker 时都会被初始化。有哪些选项可以缓存@banks,以便在Banker 的不同实例中重复使用?

【问题讨论】:

我不明白投反对票的原因。我认为问题和问题得到了很好的解释。请详细说明缺少的内容! 这个问题对我来说很清楚,但可能投票者认为问题陈述本身有点宽泛(如果是这样的话,我不同意)。或者标题与您实际要求的内容不完全匹配(不是真正的否决理由imo)。 【参考方案1】:

我不认为Struct 在这里给你买任何东西。这样做怎么样?

代码

class Banker
  @all_banks = 

  class << self
    attr_reader :all_banks
  end

  attr_reader :banks

  def initialize(banks)
    @banks = banks.keys
    banks.each  |k,v| self.class.all_banks[k] = v 
  end

  def find_by_bic(bic)
    return nil unless @banks.include?(bic)
    self.class.all_banks[bic]
  end
end

需要注意self.class中的self来区分self的类和关键字class

示例

b1 = Banker.new( '1234567' =>  name: 'Citibank', codes: ["1", "2"] ,
                  '7654321' =>  name: 'Wells Fargo', codes: ['4']  )
b1.banks
  #=> ["1234567", "7654321"]
Banker.all_banks
  #=> "1234567"=>:name=>"Citibank", :codes=>["1", "2"],
  #    "7654321"=>:name=>"Wells Fargo", :codes=>["4"]
b1.find_by_bic '7654321'
  #=> :name=>"Wells Fargo", :codes=>["4"]
b1.find_by_bic '1234567'
  #=> :name=>"Citibank", :codes=>["1", "2"]
b1.find_by_bic '0000000'
  #=> nil

b2 = Banker.new( '6523155' =>  name: 'Bank of America', codes: ["3"] ,
                  '1234567' =>  name: 'Citibank', codes: ["1", "2"]  )
b2.banks
  #=> ["6523155", "1234567"]
Banker.all_banks
  #=> "1234567"=>:name=>"Citibank", :codes=>["1", "2"],
  #    "7654321"=>:name=>"Wells Fargo", :codes=>["4"],
  #    "6523155"=>:name=>"Bank of America", :codes=>["3"]
b2.find_by_bic '6523155'
  #=> :name=>"Bank of America", :codes=>["3"]
b2.find_by_bic '1234567'
  #=> :name=>"Citibank", :codes=>["1", "2"]
b2.find_by_bic '7654321'
  #=> nil

替代品

如果您愿意,也可以添加类方法:

def self.new(banks)
  banks.each  |k,v| all_banks[k] = v 
  super
 end

并删除initialize 中的第一行。

或者,如果您有所有银行的完整列表,您可以改为将 all_banks 设为常量:

ALL_BANKS = "1234567"=>:name=>"Citibank", :codes=>["1", "2"],
             "7654321"=>:name=>"Wells Fargo", :codes=>["4"],
             "6523155"=>:name=>"Bank of America", :codes=>["3"]

def find_by_bic(bic)
  return nil unless @banks.include?(bic)
  ALL_BANKS[bic]
end

并将initialize 更改为:

def initialize(bics)
  @banks = bics
end

其中bicsbic 值的数组。

【讨论】:

【参考方案2】:

要在实例之间共享不可变数据,您可以使用冻结类变量:@@banks ||= [...].freeze

【讨论】:

以上是关于如何在 Ruby 中实现查找类?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Handsontable 中实现“查找和替换”逻辑?

如何在 WPF 中实现“查找下一个”功能?

如何在Python中实现EXCEL的查找功能

ruby 本要点展示了我如何使用Ruby AWS SDK,Fog和Carrierwave在我的应用程序中实现AWS假设角色功能

正则表达式:如何在 PL/SQL 中实现负向后查找

在 Java 中实现 Mixin? [关闭]