jlstr
jlstr

Reputation: 3056

How to Refactor this simple Ruby algorithm

Ok, I have this ruby script which opens a file and passes each line to the line_parser method. This method simply changes tabs for a couple of spaces. Here it is:

$lines = []

def line_parser(line)   
    line.gsub! /\t/, '  '
    $lines[$lines.length] = line
end

f = File.open(ARGV[0], 'r').each { |line| line_parser(line) }
f.close

f = File.open(ARGV[0], 'w')
$lines.each { |line| f.puts line}
f.close

As you can see it has two loops; one loop to iterate over the lines of text inside the file an place them inside of an array. And the other loop writes the file all over again with the new lines from the recently created array.

My question is simple I think: How can I refactor this snippet so that I do all the steps described above inside one loop only?

I know it can be done, I just have not been able to do it with my current ruby knowledge.

Thanks in advance!

Upvotes: 1

Views: 182

Answers (3)

Casper
Casper

Reputation: 34328

Can we use rubygems?

require 'rubygems'
require 'facets/file'

# Version 1
File.write('outfile', File.read('infile').tr("\t", ' '))

# Version 2
File.rewrite('inoutfile') { |str| str.tr("\t", ' ') }

Upvotes: 1

emboss
emboss

Reputation: 39660

out = ""
File.open(ARGV[0], "r+") do |f|
  f.each do |line|
    out << line.gsub(/\t/, '  ')
  end
  f.pos=0
  f.print out
end

This just iterates over the file once but it still has to cache the file in a string before finally writing it to the file. If you want to avoid caching you will have to write to a temporary file first. Once done reading/writing you would simply delete the old file and replace it with the new temporary file by renaming it.

Upvotes: 2

undur_gongor
undur_gongor

Reputation: 15954

#!/usr/local/bin/ruby -w

src = File.read(ARGV[0])

File.open(ARGV[0], 'w') { | io |
  src.each_line { | line |
    io << line.gsub(/\t/, '  ')
  }
}

Please note that this is actually cheated. Reading the whole file is in fact a loop. But since you are reading and then writing to the same file, I doubt you can avoid having 2 loops (one for reading and one for writing).

Upvotes: 2

Related Questions