enum_cons chops off the tail of the collection, if it isn't evenly
divisble:
e.g.:
(1..10).each_cons(3) {|a| p a}
# outputs below
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]
[8, 9, 10]
I'd also like to get:
[9, 10, nil]
[10, nil, nil]
You want semantics that are different from #each_cons. #each_cons will give you a sliding window of n elements from the collection (see you example output). This can be used to e.g. smooth a measurement curve.
Is there anyway to do this? (The collection is an opened File, too
large to load entirely in memory.)
Yes, see below (not the best implementation though). But maybe you want to change the algorithm that needs this. What are you trying to accomplish?
I don't have a clear grasp as to how internally Ruby treats a File as
Enumerable.
You can cook your own version:
require 'enumerator'
module Enumerable
def sub_range(n)
ar = inject() do |rg, x|
rg.push x
rg.shift if rg.length > n
yield *rg if rg.length == n
rg
end
(n-1).times do
ar.push nil
ar.shift if ar.length > n
yield *ar if ar.length == n
end
self
end
def each_add(n,&b)
each(&b)
n.times { b[nil] }
self
end
def sub_range2(n,&b)
to_enum(:each_add, n-1).enum_cons(n).each {|a| b[*a]}
end
end
irb(main):036:0> [1].sub_range(3){|*x| p x}
[1, nil, nil]
=> [1]
irb(main):037:0> [1,2,3].sub_range(3){|*x| p x}
[1, 2, 3]
[2, 3, nil]
[3, nil, nil]
=> [1, 2, 3]
irb(main):038:0> (1..10).sub_range(3){|*x| p x}
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]
[8, 9, 10]
[9, 10, nil]
[10, nil, nil]
=> 1..10
irb(main):250:0> (1..1).sub_range2(3) {|*a| p a}
[1, nil, nil]
=> nil
irb(main):251:0> (1..10).sub_range2(3) {|*a| p a}
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]
[8, 9, 10]
[9, 10, nil]
[10, nil, nil]
=> nil
Kind regards
robert
···
On 23.02.2007 20:50, S. Robert James wrote: