tl; dr
我希望这两行都返回{:a => 10}
p (0..5).each_with_object({a: 0}) { |i, acc| acc[:a] += i}
p (0..Float::INFINITY).lazy.each_with_object({a: 0}) { |i, acc| acc[:a] += i}.first(5)
但是,第二行永远循环。
长版
当然,此示例已简化,但实际问题非常相似。这个想法是运行each_with_object
主体直到满足特定条件,但是此条件依赖于这个each_with_object
函数在每次迭代中生成的结果,因此停止条件必须在之后 each_with_object
。
我能得到的最接近的是
p (0..Float::INFINITY).lazy.each_with_object({a: 0}).take_while{ |i, acc| acc[:a] += i}.first(5)
但是结果不完全是我想要的,因为它返回以下内容
[[0, {:a=>10}], [1, {:a=>10}], [2, {:a=>10}], [3, {:a=>10}], [4, {:a=>10}]]
这不仅迫使我执行.last.last
,而且随着我多次迭代,它使数组极大地增长(而且它存储的是{:a => 10}
而不是{a:=>0}, {a:=>1}, {a:=>3}, ...
的5倍对我来说是个谜。
答案 0 :(得分:1)
each_with_object
仅在不传递块的情况下返回枚举数。
也许您可以创建自己的方法:
class Enumerator::Lazy
def my_each_with_object(obj)
Lazy.new(self) do |yielder, *args|
yield *args, obj
yielder << obj
end
end
end
(1..Float::INFINITY).lazy
.my_each_with_object({a: 0}) { |i, acc| acc[:a] += i }
.drop_while { |acc| acc[:a] <= 10 }
.first
#=> {:a=>15}
我使用acc[:a] <= 10
作为条件,因为您说它取决于each_with_object
计算的值。