Clean way of pausing a loop?

K

Kyle Schmitt

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
 
M

Mohit Sindhwani

Kyle said:
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
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.
 
B

Brian Adkins

Kyle Schmitt said:
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

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 }
 
R

Robert Klemme

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. :)

Cheers

robert
 
K

Kyle Schmitt

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
 
R

Robert Klemme

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. :)
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top