如何在Ruby中子类化数组?

时间:2016-01-30 01:32:36

标签: arrays ruby

我试图将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类的实例?

2 个答案:

答案 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的内容的任何内容。