Clean way of pausing a loop?

It’s Monday and it’s relatively early, so I apologize if this isn’t
worded too well.

Is there a clean way of pausing a loop/printing status every N
iterations? I often use ruby to examine log files in a one-off
fashion, and when dealing with files of 4-10 million lines, this is
the sort of thing that becomes important. Small files are, obviously,
not as big of a deal.

I know I can simply do this, but it doesn’t seem clean:

counter=0
n=100
foo.each do
|bar|
counter+=1
if (counter%n).zero?
sleep 0.1
end

Thanks,
Kyle
end

Kyle S. wrote:

counter=0
n=100
foo.each do
|bar|
counter+=1
if (counter%n).zero?
sleep 0.1
end
What’s wrong with it? I can only think that if foo allows
.each_with_index, you could avoid the counter initialization and
addition. Can’t think of anything else.

Cheers,
Mohit.
11/4/2008 | 12:09 AM.

Kyle S. [email protected] writes:

   Kyle

end

Maybe something like this?

module Enumerable
def paused_each n, sec, pause_after=true
counter = 0
self.each do |e|
yield e if pause_after
if (counter += 1) >= n
counter = 0
sleep sec
end
yield e unless pause_after
end
end
end

[1,2,3,4,5,6,7].paused_each(2,2) { |e| puts e }
puts
[1,2,3,4,5,6,7].paused_each(2,2,false) { |e| puts e }

On 03.11.2008 16:35, Kyle S. wrote:

It’s Monday and it’s relatively early, so I apologize if this isn’t
worded too well.

Is there a clean way of pausing a loop/printing status every N
iterations? I often use ruby to examine log files in a one-off
fashion, and when dealing with files of 4-10 million lines, this is
the sort of thing that becomes important. Small files are, obviously,
not as big of a deal.

You can use ARGF.lineno when reading from ARGF:

robert@fussel ~
$ seq 1 20 | ruby -e ‘ARGF.each {|l| puts “.”; puts ARGF.lineno if
ARGF.lineno % 10 == 0}’
.
.
.
.
.
.
.
.
.
.
10
.
.
.
.
.
.
.
.
.
.
20

You can use IO.lineno when reading from a stream

robert@fussel ~
$ seq 1 20 | ruby -e ‘$stdin.each {|l| puts “.”; puts $stdin.lineno if
$stdin.lineno % 10 == 0}’
.
.
.
.
.
.
.
.
.
.
10
.
.
.
.
.
.
.
.
.
.
20

Or you can use #each_with_index.

robert@fussel ~
$ seq 1 20 | ruby -e ‘$stdin.each_with_index {|l,i| puts “.”; puts i if
i % 10 == 0}’
.
0
.
.
.
.
.
.
.
.
.
.
10
.
.
.
.
.
.
.
.
.

Or you can use $.:

robert@fussel ~
$ seq 1 20 | ruby -ne ‘puts “.”; puts $. if $. % 10 == 0’
.
.
.
.
.
.
.
.
.
.
10
.
.
.
.
.
.
.
.
.
.
20

I’m sure I forgot one or more variants. :slight_smile:

Cheers

robert

On 03.11.2008 21:07, Kyle S. wrote:

Hum. Well those all work, but aren’t those basically similar to what
I’m already doing?

They at least do not do the counting manually. That’s probably more
efficient also since counting is done in C code.

Btw, there is one more option: use each_slice. :slight_smile:

I was hoping to somehow have a handler that would inject the logic
into an existing loop.

I believe we have seen such a solution in this thread already. Here’s
another one

class EI
include Enumerable

def initialize(enum, steps, &inter)
@enum = enum
@steps = steps
@inter = inter
end

def each
@enum.each_with_index do |e,i|
inter.call if i % steps == 0 && i != 0
yield e
end
self
end
end

Kind regards

robert

Hum. Well those all work, but aren’t those basically similar to what
I’m already doing?
I was hoping to somehow have a handler that would inject the logic
into an existing loop.

Oh well.

Thanks,
Kyle