Ruby 2: "Ленивое" вычисление размера (lazy size)
Примеры "ленивого" вычисления размера (lazy size) в Ruby 2, вычисление размера итератора "по требованию".
Enumerator#size
может быть вызван для определения размера итератора (количества элементов, возвращаемых итератором) без вычисления всех элементов итератора (если возможно).
(1..100).to_a.permutation(4).size # => 94109400 loop.size # => Float::INFINITY (1..100).drop_while.size # => nil
При создании итераторов с помощью to_enum
, Enumerator::New
или Enumerator::Lazy::New
также возможно определение size:
fib = Enumerator.new(Float::INFINITY) do |y| a = b = 1 loop do y << a a, b = b, b+a end end still_lazy = fib.lazy.take(1_000_000).drop(42) still_lazy.size # => 1_000_000 - 42 class Enumerable def skip(every) unless block_given? return to_enum(:skip, every) { size && (size+every)/(every + 1) } end each_slice(every+1) do |first, *ignore| yield last end end end (1..10).skip(3).to_a # => [1, 5, 9] (1..10).skip(3).size # => 3, without executing the loop
Дополнительные детали и примеры можно посмотреть тут: to_enum