Hash keys

T

Tim Wolak

Morning,

I am working on some code to gather accounts and their balances from a text
file and have a question about adding that data to a hash. While checking
to see if the account number is a key in the existing hash using
has_key?(key), can=B9t I use the variable that has the account number in it=
or
do I have to use the actual account number? When I run my code to check it I
get undefined method `has_key?' for nil:NilClass. I ran a test using just
the account number in irb and it works but I would think you could use a
variable to iterate of my list of account numbers.... Thanks in advance




class Info
attr_reader :acct, :money
=20=20
def initialize(filename)
@acct =3D File.new(filename, "r")
end
f =3D Info.new("Balances20080415.txt")
act =3D f.acct
act.each do |list|
#covert me to a string
futbal =3D list.to_s
#Pull accounts
office =3D futbal[21..23]
if office =3D=3D "RPT"
next
else=20=20
acctnum =3D futbal[24..28]
lv =3D futbal[217..230]
lvind =3D futbal[215..215]
lvadd =3D lvind+lv
lvadd.to_f/100
end
#if Negitave vlaues
if lvind =3D=3D "-"
lvnegfloat =3D lv.to_f/100
#print acctnum," ",lvind, lvnegfloat, "\n"
#puts lvadd
sktylist =3D Hash.new("")
#if(sktylist.has_key?(23))
# sktylist =3D { acctnum =3D> lvind,lvnegfloat }
=20=20=20=20=20=20=20=20=20=20=20=20=20
sktylist[acctnum] =3D lvind,lvnegfloat
sktylist.each { |key, value| puts "#{key} equals #{value}" }
#else Positive Values
=20=20=20=20=20=20=20=20=20=20=20=20=20=20
elsif sktylist.has_key?('acctnum')
puts "found #{key}second key"
#lvposflt =3D lv.to_f/100
=20=20=20=20=20=20=20=20=20=20=20=20=20=20
#print acctnum, " ", lvposflt, "\n"
end
end
=20=20=20=20=20=20
end

--=20
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
 
T

Trans

Morning,

I am working on some code to gather accounts and their balances from a tex= t
file and have a question about adding that data to a hash. While checking=
to see if the account number is a key in the existing hash using
has_key?(key), can=B9t I use the variable that has the account number in i= t or
do I have to use the actual account number? When I run my code to check it= I
get undefined method `has_key?' for nil:NilClass. I ran a test using just=
the account number in irb and it works but I would think you could use a
variable to iterate of my list of account numbers.... Thanks in advance

class Info
attr_reader :acct, :money

def initialize(filename)
@acct =3D File.new(filename, "r")
end
f =3D Info.new("Balances20080415.txt")
act =3D f.acct
act.each do |list|
#covert me to a string
futbal =3D list.to_s
#Pull accounts
office =3D futbal[21..23]
if office =3D=3D "RPT"
next
else
acctnum =3D futbal[24..28]
lv =3D futbal[217..230]
lvind =3D futbal[215..215]
lvadd =3D lvind+lv
lvadd.to_f/100
end
#if Negitave vlaues
if lvind =3D=3D "-"
lvnegfloat =3D lv.to_f/100
#print acctnum," ",lvind, lvnegfloat, "\n"
#puts lvadd
sktylist =3D Hash.new("")
#if(sktylist.has_key?(23))
# sktylist =3D { acctnum =3D> lvind,lvnegfloat }

sktylist[acctnum] =3D lvind,lvnegfloat
sktylist.each { |key, value| puts "#{key} equals #{value}" }=
#else Positive Values

elsif sktylist.has_key?('acctnum')
puts "found #{key}second key"
#lvposflt =3D lv.to_f/100

#print acctnum, " ", lvposflt, "\n"
end
end

end

Your if clauses looked messed up. The no method error doesn't have
anything to do with the key of has_key. You actually have no hash to
speak of.

T.
 
S

Siep Korteling

Tim said:
(...)
Basically what I'm trying to do here is gather the account balances and
account numbers and store them in a hash and if there are accounts with
the
same number to store their balances as an array in the hash value to add
them later when I iterate over the hash.

If there is a better way to do this that I'm not thinking of please
share
with me so I can better my ruby knowledge.

Thanks!
Tim

The following code does not store an array in a hash, it just stores a
running total:

DATA.gets
#DATA is the stuff below __END__
#you can treat it like a file.
#DATA.gets just gets the first line and ignores it.

totalled = Hash.new(0)
#Thanks to the (0) parameter, totalled will return 0 if a key is not
found.

DATA.each do |line|
ar_line = line.split(",")
account, balance = ar_line[0], ar_line[1].to_f
totalled[account] = totalled[account] + balance
#this line does the job. For the first line
#read in the loop, the key "101" is not found in the hash
#so it returns 0. Then the balance is added.
#The key and the new (running) balance are stored.
#A shorter way to write this is:
#totalled[account] += balance
end
p totalled

__END__
account,balance
101,100.00
102,500.00
101,-57.00
103,0.50
102,1


##end code

prints: {"101"=>43.0, "102"=>501.0, "103"=>0.5}

If you really need the hash with an array, replace the first line with:
totalled = Hash.new([])
(giving a 'default value' of an empty array); Also replace this line:
totalled[account] = totalled[account] + balance
with
totalled[account]=totalled[account]<<balance
HTH,

Siep
 
G

Gordon Thiesfeld

The first if does return a hash with the keys and values so I know that
works. The first one is for any negative values as it is only indicated by
a 0 or a - in position 215 of the string. The second if is for the positive
values, so I'm guessing that when the script is processing the lines and has
a positive value its not skipping the negative if and going to the elsif to
process and store the info in the hash.

Basically what I'm trying to do here is gather the account balances and
account numbers and store them in a hash and if there are accounts with the
same number to store their balances as an array in the hash value to add
them later when I iterate over the hash.

If there is a better way to do this that I'm not thinking of please share
with me so I can better my ruby knowledge.

Thanks!
Tim

Here are some ideas. You create the Hash using a block, this will
give you a default value for newly created hash pairs. You iterate
over the file line by line, you skip the lines that have an office
code of RPT. Otherwise, you pull out the account number and the
balance. You add the balance in to the hash pair for that account
number. If no values have been put in yet, you'll add it to 0.
Otherwise, you'll add it to the previous value. There is no need to
handle negative numbers in some special fashion, Ruby will know if
it's a negative number when it sees the '-' at the beginning of the
string.

I'm assuming you don't want whatever is at position 216 to be part of
your balance, so you concatenate the character at 215 to the rest of
the balance in positions 217 to 230. You now have a string
representation of your balance, you call to_f on that and it will be a
positive or negative number.

act = File.new("Balances20080415.txt", 'r')

# The default for a newly created value is 0

act.each do |list|
# list already is a string, no need to
# do this
# futbal = list.to_s
#Pull accounts
office = list[21..23]
unless office == "RPT"
acctnum = list[24..28]
lvind = list[215,1]
lvnum = list[217..230]
lv = (lvind+lvnum).to_f/100
sktylist[acctnum] += lv
end
end

p sktylist
 

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

Similar Threads

Hashes 6
Negative nums 1
changing hash key 5
n00b question 4
inserting hash data into email 0
Conta occorrenze in Hash 2
Ruby Hash Keys and Related Questions 6
[QUIZ SOLUTION] Happy Numbers (#93) 3

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top