[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Clean way of pausing a loop?

Kyle Schmitt

11/3/2008 3:35:00 PM

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

5 Answers

Mohit Sindhwani

11/3/2008 4:08:00 PM

0

Kyle Schmitt 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.
>
> 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.


Brian Adkins

11/3/2008 4:55:00 PM

0

Kyle Schmitt <kyleaschmitt@gmail.com> writes:

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

Robert Klemme

11/3/2008 5:20:00 PM

0

On 03.11.2008 16:35, Kyle Schmitt 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. :-)

Cheers

robert

Kyle Schmitt

11/3/2008 8:07:00 PM

0

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

Robert Klemme

11/3/2008 8:20:00 PM

0

On 03.11.2008 21:07, Kyle Schmitt 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. :-)

> 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