Iterators and blocks question

I am new to ruby and am trying to learn my way around it. I saw the
following example somewhere on the net to read a file line by line and
list it to the console:

IO.foreach("test.txt") {|line| puts line}

This works great. However, I am trying to take the next step(s). For
starters, I would like to modify the above code such that it lets me
prepend the line numbers to each line as it is listed to the console.
Something similar to the listing below for example:

1. First line from the file..
2. Second line from the file...
..
..
12. Last line from the file.

What is the Ruby idiom for doing this? Using the iterator and the code
block?

Thanks in advance.
Regards,

Bharat

···

--
Posted via http://www.ruby-forum.com/.

Bharat Ruparel wrote:

I am new to ruby and am trying to learn my way around it. I saw the
following example somewhere on the net to read a file line by line and
list it to the console:

IO.foreach("test.txt") {|line| puts line}

This works great. However, I am trying to take the next step(s). For
starters, I would like to modify the above code such that it lets me
prepend the line numbers to each line as it is listed to the console.
Something similar to the listing below for example:

1. First line from the file..
2. Second line from the file...
..
12. Last line from the file.

What is the Ruby idiom for doing this? Using the iterator and the code
block?

Thanks in advance.
Regards,

Bharat

counter = 1
IO.foreach("test.txt") {|line| puts "#{counter}. #{line}"; counter += 1}

Namaste Bharat.
You might try something like
require 'mathn'
width = (Math.log((rl = IO.readlines("test.txt")).length)/
Math.log(10)).floor + 1
rl.each_with_index{ |line, k| print "%#{width}d. " % k + line}

Regards, Bret

···

On Feb 8, 2:36 pm, Bharat Ruparel <brupa...@mercury.com> wrote:

IO.foreach("test.txt") {|line| puts line}

This works great. However, I am trying to take the next step(s). For
starters, I would like to modify the above code such that it lets me
prepend the line numbers to each line as it is listed to the console.
Something similar to the listing below for example:

1. First line from the file..
2. Second line from the file...
.
.
12. Last line from the file.

What is the Ruby idiom for doing this? Using the iterator and the code
block?

Thanks in advance.
Regards,
Bharat

Posted viahttp://www.ruby-forum.com/.

Thanks.
Bharat

···

--
Posted via http://www.ruby-forum.com/.

Following up to myself, the idea is to keep from indenting the lines
differently
every time the line number passes a power of 10.
Regards, Bret

···

On Feb 8, 3:25 pm, "oinkoink" <oinkoink+u...@rexx.com> wrote:

require 'mathn'
width = (Math.log((rl = IO.readlines("test.txt")).length)/
Math.log(10)).floor + 1
rl.each_with_index{ |line, k| print "%#{width}d. " % k + line}

An injectified version of this:

require 'enumerator'
IO.to_enum(:foreach, "test.txt").inject(0) do |counter, line|
   puts "#{counter}. #{line}"
   counter + 1
end

:slight_smile:

  robert

···

On 08.02.2007 23:44, Timothy Hunter wrote:

Bharat Ruparel wrote:

counter = 1
IO.foreach("test.txt") {|line| puts "#{counter}. #{line}"; counter += 1}

width = (rl = IO.readlines("test.txt")).length.to_s.length
   format = "%2$#{width}d: %1$s" # see Kernel#sprintf
   rl.each_with_index { |*ary| ary[1] += 1; print format % ary }

The ary[1]+=1 part is to make the numbers 1-based. If you're OK with the zero, leave it out. Of course, if you want to start with 1, it makes more sense to do:

   number = 0
   rl.each { |line| number += 1; print format % [ line, number ] }

or

   rl.each_with_index { |line,number| print format % [ line, number+1 ] }

But then you could go back to the simpler format string and swap the order of the args yourself.

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

···

On Feb 8, 2007, at 7:05 PM, oinkoink wrote:

On Feb 8, 3:25 pm, "oinkoink" <oinkoink+u...@rexx.com> wrote:

require 'mathn'
width = (Math.log((rl = IO.readlines("test.txt")).length)/
Math.log(10)).floor + 1
rl.each_with_index{ |line, k| print "%#{width}d. " % k + line}

Following up to myself, the idea is to keep from indenting the lines
differently
every time the line number passes a power of 10.
Regards, Bret

Thanks Robert,
Tim Hunter's solution seems most straightforward to me. Which is:
counter = 1
IO.foreach("test.txt") {|line| puts "#{counter}. #{line}"; counter += 1}

The solution that you present:
require 'enumerator'
IO.to_enum(:foreach, "test.txt").inject(0) do |counter, line|
    puts "#{counter}. #{line}"
    counter + 1
end

Seems like a good one too, except more indirect. When would you
recommend using one over another? Or is it largely a matter of taste?
Also, why do you have to "require" the enumerator module here whereas
Tim's solution didn't. I did a search on "ri IO" and it shows that IO
includes enumerable (it is not enumerator, I know). Also it shows that
foreach is a class method for IO class whereas I could not find anything
on to_enum. Is there a way to get RoR style online API docs for Ruby?
I find "ri" a bit primitive.

Bharat

···

--
Posted via http://www.ruby-forum.com/.

Thank you gentlemen.
Regards,
Bharat

···

--
Posted via http://www.ruby-forum.com/.

Thanks Robert,
Tim Hunter's solution seems most straightforward to me. Which is:
counter = 1
IO.foreach("test.txt") {|line| puts "#{counter}. #{line}"; counter += 1}

The solution that you present:
require 'enumerator'
IO.to_enum(:foreach, "test.txt").inject(0) do |counter, line|
    puts "#{counter}. #{line}"
    counter + 1
end

Seems like a good one too, except more indirect. When would you recommend using one over another? Or is it largely a matter of taste?

Yes. And there is a ton of other equally good solutions.

Also, why do you have to "require" the enumerator module here whereas Tim's solution didn't.

Because the module is not loaded by default. (IIRC that will change / has changed in Ruby 1.9).

> I did a search on "ri IO" and it shows that IO

includes enumerable (it is not enumerator, I know). Also it shows that foreach is a class method for IO class whereas I could not find anything on to_enum. Is there a way to get RoR style online API docs for Ruby? I find "ri" a bit primitive.

I usually use http://www.ruby-doc.org/

For example

http://www.ruby-doc.org/core/classes/Enumerable/Enumerator.html

Kind regards

  robert

···

On 09.02.2007 15:39, Bharat Ruparel wrote:

How can one go about looking up this sort of information online? I like
to do a bit of my homework before asking the question except I don't
know where the library is....

···

--
Posted via http://www.ruby-forum.com/.

Thanks Robert.

···

--
Posted via http://www.ruby-forum.com/.

Try this at your prompt:

ri Kernel#sprintf

ri IO.readlines

and so on. If you don't have a copy of the pickaxe (Programming Ruby; http://pragmaticprogrammer.com/titles/ruby/index.html\) then that should be your first book.

Online of course you have:

The Ruby Home Page: Ruby Programming Language

from which you have links to *much* more than it would be worth my repeating.

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

···

On Feb 8, 2007, at 11:03 PM, Bharat Ruparel wrote:

How can one go about looking up this sort of information online? I like
to do a bit of my homework before asking the question except I don't
know where the library is....

and so on. If you don't have a copy of the pickaxe (Programming
Ruby; http://pragmaticprogrammer.com/titles/ruby/index.html\) then
that should be your first book.

The old version is available to read on-line:
http://www.rubycentral.com/book/

It was written for Ruby 1.6, but it basically applies to Ruby 1.8 as well
(it just doesn't document the additions :slight_smile: And if you like it, as you
probably will, you can then buy the paper or PDF version of the new one.

Online of course you have:

The Ruby Home Page: Ruby Programming Language

and also:
http://wiki.rubygarden.org/Ruby

···

On Fri, Feb 09, 2007 at 01:18:10PM +0900, Rob Biedenharn wrote: