On 23.02.2007 20:50, S. Robert J. wrote:
[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