我试图将Array
子类化,以实现一个返回map
类实例的Record
方法。我试图创造一种“懒惰”#34;只需要实例化对象的数组,因为它们需要一次尝试并避免分配太多的Ruby对象。我希望通过在每次迭代中仅实例化一个对象来更好地利用垃圾收集器。
class LazyArray < Array
def initialize(results)
@results = results
end
def map(&block)
record = Record.new(@results[i]) # how to get each item from @results for each iteration?
# how do I pass the record instance to the block for each iteration?
end
end
simple_array = [{name: 'foo'}, {name: 'bar'}]
lazy_array_instance = LazyArray.new(simple_array)
expect(lazy_array_instance).to be_an Array
expect(lazy_array_instance).to respond_to :map
lazy_array_instance.map do |record|
expect(record).to be_a Record
end
如何将Array
子类化,以便我可以在每次迭代中返回Record类的实例?
答案 0 :(得分:1)
所以你有一个简单属性数组或者一些这样的属性,你想在调用map
块之前实例化一个对象。按值逐行进行预处理。
class Record
attr_accessor :name
def initialize(params={})
self.name = params[:name]
end
end
require 'delegate'
class MapEnhanced < SimpleDelegator
def map(&block)
@delegate_ds_obj.map do |attributes|
object = Record.new(attributes)
block.call(object)
end
end
end
array = MapEnhanced.new([{name: 'Joe'}, {name: 'Pete'}])
array.map {|record| record.name }
=> ["Joe" "Pete"]
替代方案(允许您保留object.is_a? Array
)
class MapEnhanced < Array
alias_method :old_map, :map
def map(&block)
old_map do |attributes|
object = Record.new(attributes)
block.call(object)
end
end
end
答案 1 :(得分:1)
据我所知,你根本不应该做这样的事情。使用.lazy
,您可以对数组执行延迟评估:
simple_array_of_results.lazy.map do |record|
# do something with Record instance
end
现在,你有一些奇怪的情况,你正在做类似的事情 -
SomeOperation(simple_array_of_results)
并且你要么SomeOperation
懒得去做,或者你想让输出变得懒惰 -
lazily_transformed_array_of_results = SomeOperation(simple_array_of_results)
page_of_results = lazily_transformed_array_of_results.take(10)
如果这听起来不错......我希望它如下:
SomeOperation(simple_array_of_results.lazy)
这有用吗?毕竟,array.lazy
会返回一个响应map
的对象。
编辑: ...再次阅读你的问题后,看起来你真正想要的是:
SomeOperation(simple_array_of_results.lazy.collect{|r| SomeTransform(r)})
SomeTransform
是您正在考虑的内容,它会获取初始数据并使用它来创建对象(“根据需要”变为“一次一个”)。 SomeOperation
是需要通过响应map
的内容的任何内容。