Iterators and blocks question


#1

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…

  3. 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


#2

Bharat R. wrote:

Regards,

Bharat

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


#3

Thanks.
Bharat


#4

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


#5

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


#6

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


#7

Thank you gentlemen.
Regards,
Bharat


#8

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…


#9

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


#10

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

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


#11

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


#12

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

:slight_smile:

robert


#13

Thanks Robert.


#14

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/Enumerator.html

Kind regards

robert