Ruby noob with a coming from Python question

J

Jeff Carlson

I am very new to ruby and thought I would start with my simplest python
script and port it over and along the way, learn the "ruby way" of doing
things. My solution so far is unsatisfactory and long. If you have any
suggestions, most especially about the "ruby way" to write the file2Map
method, I would appreciate it and all of my future ruby programs would
also appreciate it.

Cheers,
Jeff Carlson

-------------------------------------------------------------
#!/usr/bin/python
# print statistics for seti@home jobs
from mx.DateTime import TimeDelta
import sys

# this method takes a file with key/value pairs, seperated by "="
# and makes a map of the file, keys and values, the length of the
# map is the length of the file
def getMapFromFile(fname):
lines = open(fname).readlines()
return dict([line.split("=") for line in lines])

# make maps of the two files
sMap = getMapFromFile(sys.argv[1])
uMap = getMapFromFile(sys.argv[2])

prog = float(sMap["prog"].strip())*100
et = TimeDelta(seconds=float(sMap["cpu"].strip()))

#print results
print '%.2f%c completed in %d:%02d:%02d' % (prog, '%', et.hour, /
et.minute, et.second)
print 'units of work so far %s' % (uMap["nresults"].strip())
 
J

Jeff Carlson

Oops, I meant the *getMapFromFile* function. If I could see the ruby
way of writing a method to take a file of the form
key1=value1
key2=value2
etc
and easily make it into a hash in a concise way (as in the python
example) that would be great.
 
E

ES

Jeff said:
I am very new to ruby and thought I would start with my simplest python
script and port it over and along the way, learn the "ruby way" of doing
things. My solution so far is unsatisfactory and long. If you have any
suggestions, most especially about the "ruby way" to write the file2Map
method, I would appreciate it and all of my future ruby programs would
also appreciate it.

Cheers,
Jeff Carlson

-------------------------------------------------------------
#!/usr/bin/python
# print statistics for seti@home jobs
from mx.DateTime import TimeDelta
import sys

# this method takes a file with key/value pairs, seperated by "="
# and makes a map of the file, keys and values, the length of the
# map is the length of the file
def getMapFromFile(fname):
lines = open(fname).readlines()
return dict([line.split("=") for line in lines])

This should work:

def map_from(file)
Hash[*File.readlines(file).map {|line| line.split '='}.flatten]
end

Broken down, File.readlines makes an Array of lines in the file; we
then #map it to split each line into the two parts and then #flatten
the Array from [[key1, val1], [key2, val2]] to [key1, val1, key2, val2].

This syntax can be used by Hash[], so we just 'splat' the Array
to individual values by using the * operator.
# make maps of the two files
sMap = getMapFromFile(sys.argv[1])
uMap = getMapFromFile(sys.argv[2])

prog = float(sMap["prog"].strip())*100
et = TimeDelta(seconds=float(sMap["cpu"].strip()))

#print results
print '%.2f%c completed in %d:%02d:%02d' % (prog, '%', et.hour, /
et.minute, et.second)
print 'units of work so far %s' % (uMap["nresults"].strip())

E
 
L

Logan Capaldo

Oops, I meant the *getMapFromFile* function. If I could see the
ruby way of writing a method to take a file of the form
key1=value1
key2=value2
etc
and easily make it into a hash in a concise way (as in the python
example) that would be great.

Jeff said:
I am very new to ruby and thought I would start with my simplest
python script and port it over and along the way, learn the "ruby
way" of doing things. My solution so far is unsatisfactory and
long. If you have any suggestions, most especially about the
"ruby way" to write the file2Map method, I would appreciate it and
all of my future ruby programs would also appreciate it.
Cheers,
Jeff Carlson
-------------------------------------------------------------
#!/usr/bin/python
# print statistics for seti@home jobs
from mx.DateTime import TimeDelta
import sys
# this method takes a file with key/value pairs, seperated by "="
# and makes a map of the file, keys and values, the length of the
# map is the length of the file
def getMapFromFile(fname):
lines = open(fname).readlines()
return dict([line.split("=") for line in lines])
# make maps of the two files
sMap = getMapFromFile(sys.argv[1])
uMap = getMapFromFile(sys.argv[2])
prog = float(sMap["prog"].strip())*100
et = TimeDelta(seconds=float(sMap["cpu"].strip()))
#print results
print '%.2f%c completed in %d:%02d:%02d' % (prog, '%', et.hour, /
et.minute, et.second)
print 'units of work so far %s' % (uMap["nresults"].strip())


results = File.open(file_name) do |file|
file.map { |line|
line.chomp.split(/=/)[0..1]
}
end.inject({}) { |results, (key, val)| results[key] = val; results }


...OR...

results = {}

File.open(file_name) do |file|
file.each do |line|
line.chomp!
key, val = line.split(/=/)
results[key] = val
end
end

results
 
J

James Edward Gray II

def map_from(file)
Hash[*File.readlines(file).map {|line| line.split '='}.flatten]
end

Pretty much the same thing, but this should allow you to leave of
some strips later, I hope:

def hash_from_file( file_name )
Hash[*File.read(file_name).split("\n").map { |line| line.split
("=") }.flatten]
end

James Edward Gray II
 
K

Kevin Ballard

James said:
def map_from(file)
Hash[*File.readlines(file).map {|line| line.split '='}.flatten]
end

Pretty much the same thing, but this should allow you to leave of
some strips later, I hope:

def hash_from_file( file_name )
Hash[*File.read(file_name).split("\n").map { |line| line.split
("=") }.flatten]
end

James Edward Gray II

Erm, what do you mean "to leave of some strips"? The only difference I
can see is readlines(file) -> read(file_name).split("\n"), and I'm not
sure what the difference is.
 
D

Devin Mullins

def hash_from_file(file_name)
IO.read(file_name).inject({}) { |hash, line| hash.merge
Hash[*line.split(/=/)] }
end

Devin
 
J

James Edward Gray II

On Oct 11, 2005, at 3:16 PM, ES wrote:

Pretty much the same thing, but this should allow you to leave of
some strips later, I hope:

def hash_from_file( file_name )
Hash[*File.read(file_name).split("\n").map { |line| line.split
("=") }.flatten]
end

James Edward Gray II

Erm, what do you mean "to leave of some strips"? The only difference I
can see is readlines(file) -> read(file_name).split("\n"), and I'm not
sure what the difference is.

Let's ask Ruby:

Neo:~/Desktop$ cat multiline_data.rb
#!/usr/local/bin/ruby -w

data = DATA.pos

p DATA.readlines

DATA.seek data

p DATA.read.split("\n")

__END__
Line one.
Line two.
Line three.
Neo:~/Desktop$ ruby multiline_data.rb
["Line one.\n", "Line two.\n", "Line three.\n"]
["Line one.", "Line two.", "Line three."]

If you go back and look at the original code now, I was hoping that
would save all the random calls to strip() when Hash data is
accessed, thought the "=" split() pattern may also need to become /
\s*=\s*/ to get leading whitespace.

James Edward Gray II
 
K

Kevin Ballard

James said:
If you go back and look at the original code now, I was hoping that
would save all the random calls to strip() when Hash data is
accessed, thought the "=" split() pattern may also need to become /
\s*=\s*/ to get leading whitespace.

Ohh, leave *off* some strips. I see what you mean.

Perhaps an easier solution would be to just use readlines, but then
call strip() on both key and value? That takes care of any whitespace,
whether it be leading the line, trailing, or around the equals sign.
 
J

James Edward Gray II

Ohh, leave *off* some strips. I see what you mean.

Ah, I see now. You're right, that was a terrible typo on my part! :(
Perhaps an easier solution would be to just use readlines, but then
call strip() on both key and value? That takes care of any whitespace,
whether it be leading the line, trailing, or around the equals sign.

Yes, definitely.

James Edward Gray II
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top