[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Another Newb asks questions.

Joseph Divelbiss

12/30/2005 7:55:00 PM

Ok, recently started "trying" to learn this wonderful language, but am
experiencing major problems with a section of code that I think "should"
work.. and my brain is so convinced that I did it correctly that I can't
see some obvious error. Ive isolated the problem to this single section
of code.. what do you all think?


#This section reads data files and saves odd lines as the key, even
lines as the value for a hash.

if Dir["/Program Files/.../data/"].last != nil
script_data_dir = "/Program Files/.../data/"
end
build_hash = Proc.new do |type|
hash.new = type_hash
file.open("#{script_data_dir}type.dat", "r") { |file|
data = file.readlines
data.delete_if { |line| line.chomp.empty? }
until data.empty?
$type_hash[data.shift.chomp] = data.shift.chomp
end
}
end
build_hash.call(test)
end

Thanks for any help in advance..

Joseph

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


11 Answers

Wilson Bilkovich

12/30/2005 10:35:00 PM

0

On 12/30/05, Joseph Divelbiss <joseph@joseph.net> wrote:
> Ok, recently started "trying" to learn this wonderful language, but am
> experiencing major problems with a section of code that I think "should"
> work.. and my brain is so convinced that I did it correctly that I can't
> see some obvious error. Ive isolated the problem to this single section
> of code.. what do you all think?
>
>
> #This section reads data files and saves odd lines as the key, even
> lines as the value for a hash.
>
> if Dir["/Program Files/.../data/"].last != nil
> script_data_dir = "/Program Files/.../data/"
> end
> build_hash = Proc.new do |type|
> hash.new = type_hash
> file.open("#{script_data_dir}type.dat", "r") { |file|
> data = file.readlines
> data.delete_if { |line| line.chomp.empty? }
> until data.empty?
> $type_hash[data.shift.chomp] = data.shift.chomp
> end
> }
> end
> build_hash.call(test)
> end
>

This solution uses the 'enumerator' module, included in the standard library.

require 'enumerator'
Dir.chdir(script_data_dir)
type_hash = Hash.new
File.open('type.dat','r') do |file|
file.each_slice(2) do |odd, even|
type_hash[odd.chomp] = even.chomp
end
end

each_slice(2) is taking each pair of lines in the file, and passing
them to the block. So, [line1, line2], then [line3, line4], etc, etc.
You should probably also have a check in there to make sure the file
has an even number of lines.

You can also use File.exists?() to check for the presence of a directory.
abort "Oh no!" unless File.exists?("C:/Program Files/something/data_dir")


Joseph Divelbiss

12/30/2005 10:57:00 PM

0

Wilson Bilkovich wrote:

> This solution uses the 'enumerator' module, included in the standard
> library.
>

Very good solution. Ill look into it ans see how it works. Thanks.

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


Wilson Bilkovich

12/30/2005 11:07:00 PM

0

On 12/30/05, Joseph Divelbiss <joseph@joseph.net> wrote:
> Wilson Bilkovich wrote:
>
> > This solution uses the 'enumerator' module, included in the standard
> > library.
> >
>
> Very good solution. Ill look into it ans see how it works. Thanks.
>
Here's another, much uglier solution, that doesn't rely on Enumerator.
There's probably a better way, but hey, you get what you pay for. :)

Dir.chdir(script_data_dir)
type_hash = Hash.new
File.open('type.dat','r') do |file|
odd = [] ; even = []
file.each do |line|
if file.lineno % 2 == 1 then odd << line.chomp
else even << line.chomp end
end
odd.each_with_index { |line, i| type_hash[line] = even[i]}
end


Joseph Divelbiss

12/31/2005 1:03:00 AM

0

Wilson Bilkovich wrote:
> if file.lineno % 2 == 1 then

I hope youll forgive, but I seem to be at a loss for exactly what/how
this is doing..?

Any clarification?

Yeah this is my first language, first project, first week; so label me
silly.

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


Matthew Smillie

12/31/2005 1:52:00 AM

0


On Dec 31, 2005, at 1:02, Joseph Divelbiss wrote:

> Wilson Bilkovich wrote:
>> if file.lineno % 2 == 1 then
>
> I hope youll forgive, but I seem to be at a loss for exactly what/how
> this is doing..?
>
> Any clarification?
>
> Yeah this is my first language, first project, first week; so label me
> silly.

% is the modulo operator. It gives the remainder of integer division:
x / y = a (rem b)
y * a + b = x

Concrete example:
17 / 3 = 5 (rem 2)
5 * 3 + 2 = 17

Modulo returns 0 if the numerator is evenly divisible by the
denominator, so modulo 2 is a good way to check if a number is even.

m.s.


Joseph Divelbiss

12/31/2005 2:29:00 AM

0

Great answers guys! Thanks for the help.. surprisingly a part of what
was throwing me off was not having food in the tummy apparently, as when
that problem was fixed I immediately realized part of my problem was not
knowing what "file.lineno" was.. and all I can say is "duh". Makes alot
of sense now. and good trick with the % very crafty.

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


Joseph Divelbiss

12/31/2005 4:06:00 AM

0

Thanks again all.. so that you know your efforts wern't in vain I think
I learned a thing or two. The rough code (still needing debugging about
as much as I need sleep) is below. I have a high level of confidence
that I will find the typo or missing end to make it work when I wake up
in the morning.

require 'enumerator'
if Dir["#{$script_dir}data/"].last != nil
script_data_dir = "#{$script_dir}data/"
end
build_hash = Proc.new do |type|
type_hash = Hash.new
file.open("#{script_data_dir}#{type}.dat", "r") do |file|
file.each_slice(2) do |key, value|
type_hash[key.chomp] = value.chomp
end
end
$type_hash = type_hash
end
data_files=Dir["#{script_data_dir}*.dat"]
data_files.each do |name_of_file|
build_hash.call(file.basename(name_of_file, '*.*'))
end

VR,

Joseph

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


Daniel Harple

12/31/2005 5:25:00 AM

0

Joseph Divelbiss wrote:
> Thanks again all.. so that you know your efforts wern't in vain I
> think
> I learned a thing or two. The rough code (still needing debugging
> about
> as much as I need sleep) is below. I have a high level of confidence
> that I will find the typo or missing end to make it work when I
> wake up
> in the morning.
>
> require 'enumerator'
> if Dir["#{$script_dir}data/"].last != nil
> script_data_dir = "#{$script_dir}data/"
> end
> build_hash = Proc.new do |type|
> type_hash = Hash.new
> file.open("#{script_data_dir}#{type}.dat", "r") do |file|
> file.each_slice(2) do |key, value|
> type_hash[key.chomp] = value.chomp
> end
> end
> $type_hash = type_hash
> end
> data_files=Dir["#{script_data_dir}*.dat"]
> data_files.each do |name_of_file|
> build_hash.call(file.basename(name_of_file, '*.*'))
> end
>
> VR,
>
> Joseph
>
> --
> Posted via http://www.ruby-....

I see two typos --
1) file.open should be File.open ( actually, you can leave off File
too, so it is just open(..). See Kernel#open ).
2) file. basename should be File.basename

Slight style suggestions --
* The first conditional statement may be rewrote as:
script_data_dir = "#{$script_dir}data/" unless Dir["#{$script_dir}
data/"].last.nil?
* {} is equivalent to Hash.new
* Use { |x| ... } block syntax when the block has only one simple
statement (the each_slice part)

-- Daniel


Robert Klemme

12/31/2005 1:27:00 PM

0

Daniel Harple <dharple@generalconsumption.org> wrote:
> Joseph Divelbiss wrote:
>> Thanks again all.. so that you know your efforts wern't in vain I
>> think
>> I learned a thing or two. The rough code (still needing debugging
>> about
>> as much as I need sleep) is below. I have a high level of confidence
>> that I will find the typo or missing end to make it work when I
>> wake up
>> in the morning.
>>
>> require 'enumerator'
>> if Dir["#{$script_dir}data/"].last != nil
>> script_data_dir = "#{$script_dir}data/"
>> end
>> build_hash = Proc.new do |type|
>> type_hash = Hash.new
>> file.open("#{script_data_dir}#{type}.dat", "r") do |file|
>> file.each_slice(2) do |key, value|
>> type_hash[key.chomp] = value.chomp
>> end
>> end
>> $type_hash = type_hash
>> end
>> data_files=Dir["#{script_data_dir}*.dat"]

If I'm not mistaken there's a path separator missing. You better use

data_files=Dir[File.join(script_data_dir, "*.dat")]

>> data_files.each do |name_of_file|
>> build_hash.call(file.basename(name_of_file, '*.*'))

What do you use the second parameter for? The only reasonable value here
seems to be '*.dat'. Also you're trying to remove the suffix ".dat" and
reappend it again. Seems a bit strange to me.

>> end
>>
>> VR,
>>
>> Joseph
>>
>> --
>> Posted via http://www.ruby-....
>
> I see two typos --
> 1) file.open should be File.open ( actually, you can leave off File
> too, so it is just open(..). See Kernel#open ).
> 2) file. basename should be File.basename

Also it's unnecessary since Dir[] always returns basenames *only*.

> Slight style suggestions --
> * The first conditional statement may be rewrote as:
> script_data_dir = "#{$script_dir}data/" unless Dir["#{$script_dir}
> data/"].last.nil?

Even better would be to use File.directory? to test for presence of this
directory. And it would be even better if the absence of the directory
would be handled properly. As far as I can see at the moment
script_data_dir simply remains unset and thus the current working directory
is used.

> * {} is equivalent to Hash.new
> * Use { |x| ... } block syntax when the block has only one simple
> statement (the each_slice part)

Don't use blocks or procs unless you need them (i.e. want to encapsulate a
piece of code and refer it from a variable).

Don't assign a global variable as a side effect from your proc / method if
you also return it. There's especially the problem of your code that you
only get the last hash because all others are lost (the global is
overwritten all the time).

Here's what I'd probably do:

require 'enumerator'

def build_hash(file)
h = {}
File.open(file, "r") do |io|
io.each_slice(2) {|k,v| h[k.chomp]=v.chomp}
end
h
end

def build_hashes(dir='.')
h = {}
Dir[ File.join( dir, "*.dat") ].each do |file|
h[ File.basename( file, ".dat" ) ] = build_hash( File.join(dir, file) )
end
h
end

This builds a hash of hashes. Dunno whether that's what you want.

HTH

robert

Joseph Divelbiss

12/31/2005 3:31:00 PM

0

Daniel Harple wrote:

> Slight style suggestions --
> * The first conditional statement may be rewrote as:
> script_data_dir = "#{$script_dir}data/" unless Dir["#{$script_dir}
> data/"].last.nil?
> * {} is equivalent to Hash.new
> * Use { |x| ... } block syntax when the block has only one simple
> statement (the each_slice part)

Actually the first conditional will have elsifs once I get the code
working, hence the reason for writing it that way. I intend to make it
viable for unix platform for the same program aswell, in which case I
will have to look elsewhere for the appropriate directory :(

Thanks,

Joseph

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