5

考慮してください: データを生成するオブジェクトの多数のインスタンス。実行ごとに 1 回だけそのデータを生成するのは素晴らしいことです。

class HighOfNPeriods < Indicator
  def generate_data
    @indicator_data = DataStream.new
    (0..@source_data.data.count - 1).each do |i|
      if i < @params[:n_days]
      ...
      @indicator_data.add one_data
    end
  end

HighOfNPeriodswith differentparamsと differentの異なるインスタンスがあります@source_data

インジケーターの使用方法は次のとおりです。

class Strategy
  attr_accessor :indicators

  def initialize params
    ...
  end

メソッドHighOfNPeriods.generate_dataは 内から呼び出されますStrategy。それぞれStrategyが の新しいインスタンスを取得するHighOfNPeriodsため、ある種のグローバル値としてそれを引き出すことはできません。それに加えて、それはグローバルであってはなりません。

unless @indicator_dataの多くのインスタンス間でデータを共有する必要があるため、機能しませんHighOfNPeriods

したがって、質問は次のとおりです。

What is a good way to memoize the instance variable `indicator_data` 
or the object `HighOfNPeriods` when there are many different instances, 
some of which have different data?

解決策の 1 つは、ActiveRecord を使用してデータを保存することですが、現時点では、次の理由から、それは実際にはやりたくない方法です。

  1. パラメータの順列が多すぎるため、すべての生成データを事前に生成できるわけではありません。以前に生成されたかどうかを確認し、必要に応じて生成 (および保存) する方が理にかなっています。
  2. データの生成にそれほど時間はかかりません。一度生成され、実行ごとに何百回も使用される場合があります。
  3. データベースからデータを取得するよりも、オブジェクト内からデータにアクセスする方が高速です。

ルビー1.9.3

4

2 に答える 2

4

インスタンスレベルでメモ化できない場合は、1レベル上に移動して、クラスインスタンスを使用します。

class Foo
  # I used *args here for simplicity of the example code.
  def generate_data *args
    if res = self.class.cache[args]
      puts "Data in cache for #{args.inspect} is #{res}"
      return res
    end

    puts "calculating..."
    p1, p2 = args
    res = p1 * 10 + p2
    self.class.cache[args] = res
    res
  end

  def self.cache
    @cache ||= {}
    @cache
  end
end


puts Foo.new.generate_data 1, 2 
puts Foo.new.generate_data 3, 4
puts Foo.new.generate_data 1, 2
# >> calculating...
# >> 12
# >> calculating...
# >> 34
# >> Data in cache for [1, 2] is 12
# >> 12
于 2012-11-25T15:59:06.620 に答える
1

をキー、を値と@@indicator_dataするハッシュであるクラス変数を作成します。次に、作成時にメモ化を行います。[@params,@source_data]@indicator_data@@indicator_data[[@params,@source_data]]

class HighOfNPeriods < Indicator
  @@indicator_data = {}
  def generate_data
    @indicator_data = @@indicator_data[[@params, @source_data]] ||= DataStream.new
    ...
  end
end
于 2012-11-25T15:57:02.823 に答える