Hashes

Can Ruby create a hash and have a key and the value be an array?

I am taking account information from a txt file like such:
000123456778900000000-1234567890000000000000000000230000000

I¹m getting the account number and balance from each line. If the account
numbers are the same I need to add the balances together else move on to the
next. The best way for me to do that would be to store the account number
in a hash key and store the balances from the lines that have the same
account number into an array to be added together later. The code to start
gathering the info is located below. As I am extremely new to Ruby any help
would be appreciated. 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[22..24]
        if office == "RPT"
          next
        else
          acctnum = futbal[24..28]
        end
        #Pull Liquidating values
          lv = futbal[217..231]
        #Pull LV Indicator
          lvind = futbal[215..215]
          #if Negitave vlaues
            if lvind == "-"
              lvnegfloat = lv.to_f/1000
              print acctnum," ",lvind, lvnegfloat, "\n"
              #else Positive Values
              else
                lvposflt = lv.to_f/1000
                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.

Hi --

Can Ruby create a hash and have a key and the value be an array?

Let's ask it :slight_smile:

$ irb
irb(main):001:0> hash = { [1,2,3] => [4,5,6] }
=> {[1, 2, 3]=>[4, 5, 6]}

That would be a yes :slight_smile:

I haven't quite analyzed your code sample but you can definitely do
the above.

David

···

On Wed, 23 Apr 2008, Tim Wolak wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

As David has shown you it is perfectly possible, but (although strings
are used quite often instead of symbols) I would be quite careful when
using mutable objects as hash keys. Look at this very simple example.
554/54 > cat hashkeys.rb && echo "--->" && ruby hashkeys.rb
h = {}

k = [1,2,3]
h[k]=[*1..3]

p h
k.pop
p h
p h[k]
--->
{[1, 2, 3]=>[1, 2, 3]}
{[1, 2]=>[1, 2, 3]}
nil

No big deal in the context but in a complex application you might get
bitten fast.
I would at least consider freezing the objects used as keys.

HTH
Robert

···

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

I didn't realize this before, but even if it's off topic, I thought
I'd bring it up.

Hashes -- during creation -- allow assignment more than once in 1.8.6
with the last one taking precedence

Is that somehow common knowledge that I missed in the Pickaxe? Just
one of those little things, I guess.

irb(main):002:0> h = {[1, 2, 3] => [4, 5, 6], [1, 2, 3] => [7, 8, 9]}
=> {[1, 2, 3]=>[7, 8, 9]}

Todd

···

On Tue, Apr 22, 2008 at 2:25 PM, David A. Black <dblack@rubypal.com> wrote:

Hi --

On Wed, 23 Apr 2008, Tim Wolak wrote:

> Can Ruby create a hash and have a key and the value be an array?
>

Let's ask it :slight_smile:

$ irb
irb(main):001:0> hash = { [1,2,3] => [4,5,6] }
=> {[1, 2, 3]=>[4, 5, 6]}

That would be a yes :slight_smile:

I haven't quite analyzed your code sample but you can definitely do
the above.

David

Hi --

As David has shown you it is perfectly possible, but (although strings
are used quite often instead of symbols) I would be quite careful when
using mutable objects as hash keys. Look at this very simple example.
554/54 > cat hashkeys.rb && echo "--->" && ruby hashkeys.rb
h = {}

k = [1,2,3]
h[k]=[*1..3]

p h
k.pop
p h
p h[k]
--->
{[1, 2, 3]=>[1, 2, 3]}
{[1, 2]=>[1, 2, 3]}
nil

No big deal in the context but in a complex application you might get
bitten fast.
I would at least consider freezing the objects used as keys.

String objects will get copied and frozen automatically:

str = "abc"

=> "abc"

h = {}

=> {}

h[str] = 1

=> 1

h

=> {"abc"=>1}

h.keys[0].equal?(str)

=> false

h.keys[0] << "def"

TypeError: can't modify frozen string
   from (irb):6:in `<<'
   from (irb):6

str << "def"

=> "abcdef"

h

=> {"abc"=>1}

Also, for mutable objects you can use rehash:

a = [1,2,3]

=> [1, 2, 3]

h[a] = 2

=> 2

a << 4

=> [1, 2, 3, 4]

h[a]

=> nil

h.rehash

=> {[1, 2, 3, 4]=>2}

h[a]

=> 2

That's not to say you might not want to freeze things sometimes, but
you can use rehash if you want the object to remain mutable.

David

···

On Thu, 24 Apr 2008, Robert Dober wrote:
   from :0

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

I didn't realize this before, but even if it's off topic, I thought
I'd bring it up.

Hashes -- during creation -- allow assignment more than once in 1.8.6
with the last one taking precedence

Is that somehow common knowledge that I missed in the Pickaxe? Just
one of those little things, I guess.

irb(main):002:0> h = {[1, 2, 3] => [4, 5, 6], [1, 2, 3] => [7, 8, 9]}
=> {[1, 2, 3]=>[7, 8, 9]}

Todd

Ouch, I guess that would be a bad thing... If I'm going line by line then I
would think I would be ok then as the hash is closed after I finish to take
on the next line correct?

Hmmm nice catch Todd!

···

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

* Todd Benson <caduceass@gmail.com> (2008-04-22) schrieb:

Hashes -- during creation -- allow assignment more than once in 1.8.6
with the last one taking precedence

I guess that

a = { 1 => 'a', 2 => 'b', 1 => 'c' }

does the same as

a = Hash.new
a[1] = 'a'
a[2] = 'b'
a[1] = 'c'

mfg, simon .... l

Hi --

I didn't realize this before, but even if it's off topic, I thought
I'd bring it up.

Hashes -- during creation -- allow assignment more than once in 1.8.6
with the last one taking precedence

Is that somehow common knowledge that I missed in the Pickaxe? Just
one of those little things, I guess.

irb(main):002:0> h = {[1, 2, 3] => [4, 5, 6], [1, 2, 3] => [7, 8, 9]}
=> {[1, 2, 3]=>[7, 8, 9]}

Todd

Ouch, I guess that would be a bad thing... If I'm going line by line then I
would think I would be ok then as the hash is closed after I finish to take
on the next line correct?

It's never exactly closed, in that sense. Hash keys are unique, so if
you key a new value, you lose the old value, even if it's not at the
time that the hash is created.

If your keys are account numbers and your values are arrays of
balances, you'll be all right as long as you don't trample the arrays
-- just add to them.

David

···

On Wed, 23 Apr 2008, Tim Wolak wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

Hi Tim,

I didn't have a close look at your original post, but in all honesty
you should probably listen to David. I just brought up a surprise in
Hash creation that I didn't expect. I don't think it would affect
your code.

Todd

···

On Tue, Apr 22, 2008 at 3:08 PM, Tim Wolak <twolak@sktydev.com> wrote:

> I didn't realize this before, but even if it's off topic, I thought
> I'd bring it up.
>
> Hashes -- during creation -- allow assignment more than once in 1.8.6
> with the last one taking precedence
>
> Is that somehow common knowledge that I missed in the Pickaxe? Just
> one of those little things, I guess.
>
> irb(main):002:0> h = {[1, 2, 3] => [4, 5, 6], [1, 2, 3] => [7, 8, 9]}
> => {[1, 2, 3]=>[7, 8, 9]}
>
> Todd
>
Ouch, I guess that would be a bad thing... If I'm going line by line then I
would think I would be ok then as the hash is closed after I finish to take
on the next line correct?

Hmmm nice catch Todd!

I guess I kind of knew that, but I was a tiny bit surprised this
happened in the Hash creation without throwing something like a "key
exists" exception. It doesn't bother me. In fact, I think I can make
some use of it.

Todd

···

On Tue, Apr 22, 2008 at 3:12 PM, David A. Black <dblack@rubypal.com> wrote:

It's never exactly closed, in that sense. Hash keys are unique, so if
you key a new value, you lose the old value, even if it's not at the
time that the hash is created.