我有一个懒惰地将数据从数据库加载到实例变量中的类,它们是数组中数组的事件。该类有几种方法可以分析这个数组,下面是我如何使用它的一个例子。
class Foo
def initialize
@a = [1,2,3,4,5] # data from database
end
def analyse
@a.reduce(:+)
end
end
d = Foo.new
result = d.analyse
我希望能够在一个非常基本的过滤器(例如:<= 3
)之后将这些方法应用于数据,我想像能够这样调用它:
d.at(3).analyse
并且at
方法仅影响链接analyse
调用的实例变量。即。
d = Foo.new # data loaded into instance var [1,2,3,4,5]
d.analyse # 15
d.at(3).analyse # 6
d.analyse # 15
我不知道如果不在at at中重新创建一个全新的对象,我怎么能做到这一点,这感觉效率低下。我有一个工作可以改变我调用at
方法的方式 - 而不是世界末日,但我想知道我想要什么是可行的,同时保持高效。
答案 0 :(得分:0)
您可以准备另一个由at
设置的实例变量,在定义时覆盖@a
,并由analyse
重置。
class Foo
def initialize
@a = [1,2,3,4,5]
end
def at i
@b = @a.select{|e| e <= i}
self
end
def array
if instance_variable_defined?(:@b)
@b.tap{remove_instance_variable(:@b)}
else
@a
end
end
def analyse
array.reduce(:+)
end
end
答案 1 :(得分:0)
我不确定如何在没有在通话中重新创建一个全新的对象的情况下如何做到这一点,这感觉效率低下。
我不认为创建一个新对象太贵了。您可以从Foo
返回新的at
,并使用原始数据的子集进行初始化。您有另一个Foo
实例和另一个Array
实例,但该数组将包含完全相同的对象:
class Foo
def initialize(a = nil)
@a = a || [1,2,3,4,5] # use a or fetch data from database
end
def analyse
@a.reduce(:+)
end
def at(max)
Foo.new(@a.take_while { |x| x <= max })
end
end
示例:
d = Foo.new
d.analyse #=> 15
d.at(3).analyse #=> 6
d.analyse #=> 15