hash adding values

T

Tim Wolak

I'm trying to insert account numbers into a hash and add the balances
together that are stored in the value. Is there a reason this is not
working?

sktylist = Hash.new("")
sktylist[@acctnum] += [value]
p sktylist
 
S

Sebastian Hungerecker

Tim said:
Is there a reason this is not
working?

sktylist =3D Hash.new("")
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sktylist[@acctnum] +=3D [value]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0p sktylist

Yes, there is: String#+ does not expect an array as an argument.
sktylist[@acctnum] +=3D value would work if value is a string.
(Alternatively you could change the hash to hold arrays instead
of strings and keep the +=3D [value] part as-is, if that's what
you want).


HTH,
Sebastian
=2D-=20
Jabber: (e-mail address removed)
ICQ: 205544826
 
T

Tim Wolak

Sebastian said:
Tim said:
Is there a reason this is not
working?

sktylist = Hash.new("")
            sktylist[@acctnum] += [value]
         p sktylist

Yes, there is: String#+ does not expect an array as an argument.
sktylist[@acctnum] += value would work if value is a string.
(Alternatively you could change the hash to hold arrays instead
of strings and keep the += [value] part as-is, if that's what
you want).


HTH,
Sebastian

So would it be easier converting it to a string or have the hash hold
arrays? All I need is the value to be an array? Is there an easy way
to do this?

Thanks for the help.
Tim
 
C

Craig Demyanovich

[Note: parts of this message were removed to make it a legal post.]

I'm trying to insert account numbers into a hash and add the balances
together that are stored in the value. Is there a reason this is not
working?

sktylist = Hash.new("")
sktylist[@acctnum] += [value]
p sktylist


According to docs for Hash.new, you're initializing the Hash and telling it
that the default value for any new elements is an empty string. Then, you
might be accessing the hash with a key that doesn't exist, so you're getting
that default value, the empty string. Then you're trying to concatenate an
array to it. I assume that you don't want to do that based on your problem
description. Maybe you want to do something like this (from an IRB session):

$ irb
h = Hash.new(0.0) => {}
h["a"] += 2.2 => 2.2
h["a"] += 3 => 5.2
h
=> {"a"=>5.2}

Regards,
Craig
 
C

Craig Demyanovich

[Note: parts of this message were removed to make it a legal post.]

Oh, you want to store the balances based on the acct. #, then you want to
iterate the balances later and sum them?
 
T

Tim Wolak

Craig said:
Oh, you want to store the balances based on the acct. #, then you want
to
iterate the balances later and sum them?

Yes, I need to take the accounts that have the same number and leave the
key that same number and sum the balances that are stored in the value
for that account. Then I can iterate over the hash and print the account
nums and balances in an email.

Thanks,
Tim
 
C

Craig Demyanovich

[Note: parts of this message were removed to make it a legal post.]

Something like this?
h = Hash.new( [] ) => {}
h["a"] << 2.2 => [2.2]
h["a"] << 3 => [2.2, 3]
sum_of_a = 0.0 => 0.0
h["a"].inject { |sum_of_a, value| sum_of_a += value } => 5.2
sum_of_a
=> 5.2

I have no idea if that's the best way to do that; I'm still earning my Ruby
chops.

Regards,
Craig
 
T

Tim Wolak

Craig said:
Something like this?
h = Hash.new( [] ) => {}
h["a"] << 2.2 => [2.2]
h["a"] << 3 => [2.2, 3]
sum_of_a = 0.0 => 0.0
h["a"].inject { |sum_of_a, value| sum_of_a += value } => 5.2
sum_of_a
=> 5.2

I have no idea if that's the best way to do that; I'm still earning my
Ruby
chops.

Regards,
Craig

I'm pretty new to ruby as well. I have the following and its saying
"can't conver float into a string". Keep in mind that the accounts and
balances are stored in variables.

class Info
attr_reader :acct, :money

def initialize(filename)
@acct = File.new(filename, "r")
end


f = Info.new("SKTYFutBalances20080415.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]
end
#Pull Liquidating values
@lv = futbal[217..230]
#Pull LV Indicator
is_negative = futbal[215..215] == '-'
value = @lv.to_f/100
value = -value if is_negative
#puts @acctnum,value
#test = @acctnum.to_sym
sktylist = Hash.new("")
sktylist[ @acctnum ] << value

p sktylist
end

end
 
C

Craig Demyanovich

[Note: parts of this message were removed to make it a legal post.]

I posted some code just before you replied. Did it help?
 
T

Tim Wolak

Craig said:
I posted some code just before you replied. Did it help?

I did not store anything when I run it with my code I posted I get:


{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
 
C

Craig Demyanovich

[Note: parts of this message were removed to make it a legal post.]

Looks like you forgot to change this line

sktylist = Hash.new("")

to

sktylist = Hash.new( [] )

which makes the default value for new elements an empty array instead of a
string. Only then can you use the << operator to push values on to the
array.

Regards,
Craig
 
T

Tim Wolak

Craig said:
Looks like you forgot to change this line

sktylist = Hash.new("")

to

sktylist = Hash.new( [] )

which makes the default value for new elements an empty array instead of
a
string. Only then can you use the << operator to push values on to the
array.

Regards,
Craig

Still get the same thing, sorry I must be doing it wrong...

class Info
attr_reader :acct, :money

def initialize(filename)
@acct = File.new(filename, "r")
end


f = Info.new("SKTYFutBalances20080415.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]
end
#Pull Liquidating values
@lv = futbal[217..230]
#Pull LV Indicator
is_negative = futbal[215..215] == '-'
value = @lv.to_f/100
value = -value if is_negative
#puts @acctnum,value
#test = @acctnum.to_sym
sktylist = Hash.new( [] )
sktylist[ @acctnum ] << value

p sktylist
end

end
 
S

Siep Korteling

Craig said:
Looks like you forgot to change this line

sktylist = Hash.new("")

to

sktylist = Hash.new( [] )

which makes the default value for new elements an empty array instead of
a
string. Only then can you use the << operator to push values on to the
array.

Regards,
Craig

You mean the block form: Hash.new{ [] }
Tim, you don't have to do classes.

f = Info.new("SKTYFutBalances20080415.txt")
@sktylist1 = Hash.new{ [] } #with curly braces
@sktylist2 = Hash.new(0)
f.each do |list|
# parsing stuff here


@sktylist1[ @acctnum ] = @sktylist1[ @acctnum ] << value
@sktylist2[ @acctnum ] += value
end

p @sktylist1
p @sktylist2

regards,

Siep
 
D

Daniel Waite

Tim said:
I did not store anything when I run it with my code I posted I get:


{}
{}
{}

Hash.new { |hash, key| hash[key] = Array.new }

Is what you will need if you intend to provide arrays as default values
to hashes.

So... (I've only skimmed your code, but I think I get the gist of your
idea, so pardon if this isn't what you were asking for)

Basically, store the raw values, then you can sum and do any number of
operations on them as you wish.

account_balances = Hash.new do |hash, key|
hash[key] = Array.new
end

array_of_accounts.each do |account|
accounts[account_name] << account.this_charge
accounts[account_name] << account.that_charge
...
end

I'm going to say ab in place of account_balances here....

ab[some_account].sum # if using Rails, else try inject

ab[some_account.inject(BigDecimal.new) do |sum, amount|
sum += amount
end
 
T

Tim Wolak

Siep said:
Craig said:
Looks like you forgot to change this line

sktylist = Hash.new("")

to

sktylist = Hash.new( [] )

which makes the default value for new elements an empty array instead of
a
string. Only then can you use the << operator to push values on to the
array.

Regards,
Craig

You mean the block form: Hash.new{ [] }
Tim, you don't have to do classes.

f = Info.new("SKTYFutBalances20080415.txt")
@sktylist1 = Hash.new{ [] } #with curly braces
@sktylist2 = Hash.new(0)
f.each do |list|
# parsing stuff here


@sktylist1[ @acctnum ] = @sktylist1[ @acctnum ] << value
@sktylist2[ @acctnum ] += value
end

p @sktylist1
p @sktylist2

regards,

Siep

Siep,

I worked with your code and its giving me the same thing I had before,
below is the output of the script. What I need to do is for example is
the account number 740 is to store it as key 740 and the value is the
sum of the balances listed. So where there is the account number listed
more than once it uses that account number and balance and moves on to
the next line and if that account number is not in the has it puts a new
account number with its balance. Hope this help make a little more
sense of what I'm trying to do.

{"700"=>[2876.86]}
{"701"=>[654.18]}
{"702"=>[47.74]}
{"705"=>[-22.26]}
{"707"=>[-120.0]}
{"708"=>[502.63]}
{"711"=>[394.13]}
{"712"=>[210.51]}
{"740"=>[7334.36]}
{"740"=>[-12430.14]}
{"740"=>[0.0]}
{"741"=>[14740.47]}
{"741"=>[44919.21]}
{"741"=>[-1009.83]}
{"742"=>[-385.35]}
{"744"=>[-2994.75]}
{"745"=>[-152.86]}
 
J

Jimmy Kofler

Tim said:
I worked with your code and its giving me the same thing I had before,
below is the output of the script. What I need to do is for example is
the account number 740 is to store it as key 740 and the value is the
sum of the balances listed. So where there is the account number listed
more than once it uses that account number and balance and moves on to
the next line and if that account number is not in the has it puts a new
account number with its balance. Hope this help make a little more
sense of what I'm trying to do.

{"700"=>[2876.86]}
{"701"=>[654.18]}
...

Could you use Hash#collate (together with an Array#sum method) for this?

http://snippets.dzone.com/posts/show/4930

Cheers,

j.k.
 
S

Siep Korteling

Tim said:
Siep Korteling wrote:
Siep,

I worked with your code and its giving me the same thing I had before,
below is the output of the script. What I need to do is for example is
the account number 740 is to store it as key 740 and the value is the
sum of the balances listed. So where there is the account number listed
more than once it uses that account number and balance and moves on to
the next line and if that account number is not in the has it puts a new
account number with its balance. Hope this help make a little more
sense of what I'm trying to do.

{"700"=>[2876.86]}
{"701"=>[654.18]}
{"702"=>[47.74]}
{"705"=>[-22.26]}
{"707"=>[-120.0]}
{"708"=>[502.63]}
{"711"=>[394.13]}
{"712"=>[210.51]}
{"740"=>[7334.36]}
{"740"=>[-12430.14]}
{"740"=>[0.0]}
{"741"=>[14740.47]}
{"741"=>[44919.21]}
{"741"=>[-1009.83]}
{"742"=>[-385.35]}
{"744"=>[-2994.75]}
{"745"=>[-152.86]}

You're creating a different hash for every line. You probably want one
hash, looking like this:
{700=>2876.86, 701=>654.18, ...}
I guess you have a Hash.new somewhere in your do-end block. (it should
be before the block) Also you are probably printing the hash inside the
block. Try it after the block.

<begin code>
@sktylist1 = Hash.new{[]}
@sktylist2 = Hash.new(0)
DATA.each do|line|
temp = line.chomp.split(",")
acctnum = temp[0]
value = temp[1].to_f
@sktylist1[acctnum] = @sktylist1[acctnum] <<value
@sktylist2[acctnum] += value
end

p @sktylist1
p @sktylist2

__END__
1234,700.00
5678,-50.00
1234,12.00
8912,35.00
5678,50.00
<end code>
 

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

changing hash key 5
Hash keys 3
n00b question 4
inserting hash data into email 0
Hashes 6
Outputting signal values to terminal Within Character Array 0
Quick sort algorithm 1
hash merge 8

Members online

No members online now.

Forum statistics

Threads
473,785
Messages
2,569,624
Members
45,319
Latest member
LorenFlann

Latest Threads

Top