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

Hi –

On Wed, 23 Apr 2008, Tim W. 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

On Tue, Apr 22, 2008 at 2:25 PM, David A. Black [email protected]id
wrote:

David
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

=> {[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!

Hi –

On Wed, 23 Apr 2008, Tim W. wrote:

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 Tue, Apr 22, 2008 at 3:12 PM, David A. Black [email protected]
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.

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:08 PM, Tim W. [email protected] wrote:

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!

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

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

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

Hi –

On Thu, 24 Apr 2008, Robert D. wrote:

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
from :0

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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs