Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Hash keys

4 views
Skip to first unread message

Tim Wolak

unread,
Apr 24, 2008, 9:11:27 AM4/24/08
to
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¹t 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

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

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

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

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

end

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


Trans

unread,
Apr 24, 2008, 10:28:41 AM4/24/08
to

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.

Tim Wolak

unread,
Apr 24, 2008, 10:40:01 AM4/24/08
to

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

Siep Korteling

unread,
Apr 24, 2008, 11:39:23 AM4/24/08
to
Tim Wolak wrote:
> (...)

> 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


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

Gordon Thiesfeld

unread,
Apr 24, 2008, 11:45:33 AM4/24/08
to
On Thu, Apr 24, 2008 at 9:40 AM, Tim Wolak <two...@sktydev.com> wrote:
> 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

0 new messages