Robert Klemme
2/24/2007 9:53:00 AM
On 23.02.2007 20:50, S. Robert James wrote:
> 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