1
所以,我不完全贊同Ruby 1.9在枚舉器上的更改,但我希望對集合進行惰性過濾/映射,例如,如何創建一個惰性枚舉器將是相當於這...Ruby 1.9列舉更改
(1..100).find_all{|x| x % 2 == 1}.map{|x| x * 2}.find_all{|x| x % 3 == 0}
我試着傳遞一個lambda到#enum_for,但它不能在我的機器上工作。
所以,我不完全贊同Ruby 1.9在枚舉器上的更改,但我希望對集合進行惰性過濾/映射,例如,如何創建一個惰性枚舉器將是相當於這...Ruby 1.9列舉更改
(1..100).find_all{|x| x % 2 == 1}.map{|x| x * 2}.find_all{|x| x % 3 == 0}
我試着傳遞一個lambda到#enum_for,但它不能在我的機器上工作。
您可以找到lazy_select和lazy_map in this blog的實現。您將只需通過這兩種方法來擴展枚舉模塊。那麼你應該可以使用
(1..100).lazy_select{|x| x % 2 == 1}.lazy_map{|x| x * 2}.lazy_select{|x| x % 3 == 0}
不幸的是,你不能用enum_for做到這一點。你必須使用類似這樣的懶惰枚舉:
class LazyEnum
include Enumerable
attr_accessor :enum, :operations
def initialize enum
@enum = enum
@operations = []
end
def each
enum.each do |x|
filtered = false
operations.each do |type, op|
if type == :filter
unless op[x]
filtered = true
break
end
else
x = op[x]
end
end
yield x unless filtered
end
end
def map! &blk
@operations << [:transform, blk]
self
end
def select! &blk
@operations << [:filter, blk]
self
end
def reject!
select! {|x| !(yield x)}
end
def dup
LazyEnum.new self
end
def map &blk
dup.map! &blk
end
def select &blk
dup.select! &blk
end
def reject &blk
dup.reject! &blk
end
end
LazyEnum.new(1..100).select{|x| x % 2 == 1}.map{|x| x * 2}.select{|x| x % 3 == 0}
#=> #<LazyEnum:0x7f7e11582000 @enum=#<LazyEnum:0x7f7e115820a0 @enum=#<LazyEnum:0x7f7e11582140 @enum=#<LazyEnum:0x7f7e115822d0 @enum=1..100, @operations=[]>, @operations=[[:filter, #<Proc:[email protected](irb):348>]]>, @operations=[[:transform, #<Proc:[email protected](irb):348>]]>, @operations=[[:filter, #<Proc:[email protected](irb):348>]]>
irb(main):349:0> LazyEnum.new(1..100).select{|x| x % 2 == 1}.map{|x| x * 2}.select{|x| x % 3 == 0}.to_a
#=> [6, 18, 30, 42, 54, 66, 78, 90, 102, 114, 126, 138, 150, 162, 174, 186, 198]
好的,這看起來比我的解決方案好... – sepp2k 2010-02-08 13:01:08