Forum: Ruby Iterators and blocks question

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Bharat R. (Guest)
on 2007-02-09 00:36
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
Timothy H. (Guest)
on 2007-02-09 00:45
(Received via mailing list)
Bharat R. wrote:
>
> Regards,
>
> Bharat
>
>
counter = 1
IO.foreach("test.txt") {|line| puts "#{counter}. #{line}"; counter += 1}
Bharat R. (Guest)
on 2007-02-09 00:57
Thanks.
Bharat
oinkoink (Guest)
on 2007-02-09 01:31
(Received via mailing list)
On Feb 8, 2:36 pm, Bharat R. <removed_email_address@domain.invalid> wrote:
> .
> 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/.

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
oinkoink (Guest)
on 2007-02-09 02:05
(Received via mailing list)
On Feb 8, 3:25 pm, "oinkoink" <removed_email_address@domain.invalid> 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
Rob B. (Guest)
on 2007-02-09 03:11
(Received via mailing list)
On Feb 8, 2007, at 7:05 PM, oinkoink wrote:
> On Feb 8, 3:25 pm, "oinkoink" <removed_email_address@domain.invalid> 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

   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 B.    http://agileconsultingllc.com
removed_email_address@domain.invalid
Bharat R. (Guest)
on 2007-02-09 05:47
Thank you gentlemen.
Regards,
Bharat
Bharat R. (Guest)
on 2007-02-09 06:03
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....
Rob B. (Guest)
on 2007-02-09 06:18
(Received via mailing list)
On Feb 8, 2007, at 11:03 PM, Bharat R. 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....

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:  http://www.ruby-lang.org/en/

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

-Rob

Rob B.    http://agileconsultingllc.com
removed_email_address@domain.invalid
Brian C. (Guest)
on 2007-02-09 11:04
(Received via mailing list)
On Fri, Feb 09, 2007 at 01:18:10PM +0900, Rob B. wrote:
> 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 :-) 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:  http://www.ruby-lang.org/en/

and also:
http://wiki.rubygarden.org/Ruby
Robert K. (Guest)
on 2007-02-09 11:06
(Received via mailing list)
On 08.02.2007 23:44, Timothy H. wrote:
> Bharat R. wrote:

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

An injectified version of this:

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

:-)

  robert
Bharat R. (Guest)
on 2007-02-09 16:39
Thanks Robert,
Tim H.'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
Robert K. (Guest)
on 2007-02-09 20:46
(Received via mailing list)
On 09.02.2007 15:39, Bharat R. wrote:
>  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/En...

Kind regards

  robert
Bharat R. (Guest)
on 2007-02-09 21:33
Thanks Robert.
This topic is locked and can not be replied to.