Hash adding values

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

···

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

Tim Wolak wrote:

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

···

--
Jabber: sepp2k@jabber.org
ICQ: 205544826

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

···

On Wed, May 7, 2008 at 1:43 PM, Tim Wolak <tim.wolak@gmail.com> wrote:

Sebastian Hungerecker wrote:

Tim Wolak wrote:

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

···

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

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

Craig Demyanovich wrote:

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

···

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

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

Craig Demyanovich wrote:

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

···

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

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

Craig Demyanovich wrote:

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:

{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}

···

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

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

Craig Demyanovich wrote:

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

···

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

Craig Demyanovich wrote:

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

···

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

Tim Wolak wrote:

Craig Demyanovich wrote:

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:

{}
{}
{}

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

···

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

Siep Korteling wrote:

Craig Demyanovich wrote:

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]}

···

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

Tim Wolak wrote:

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.

···

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

Tim Wolak wrote:

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>

···

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

Did you have a look at the code I posted a few weeks ago for this?

http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/c01af1814e46cc08?fwc=2

···

On Wed, May 7, 2008 at 3:44 PM, Siep Korteling <s.korteling@gmail.com> wrote:

Tim Wolak wrote: