making hash key from arrays

A

Arihan Sinha

Hi All,

I've two arrays,

keys = [300,300,301,301,301,302,302]

values = [1, 2, 1, 3, 4, 3, 4]

both the arrays have equal size.

I need to create a hask

hsh = {"300" =>["1","2"],"301" => ["1","3","4"],"302"=>["3","4"]}

Could any one please put the ruby code for this.


Cheers
A
 
A

Alex Gutteridge

Hi All,

I've two arrays,

keys = [300,300,301,301,301,302,302]

values = [1, 2, 1, 3, 4, 3, 4]

both the arrays have equal size.

I need to create a hask

hsh = {"300" =>["1","2"],"301" => ["1","3","4"],"302"=>["3","4"]}

Could any one please put the ruby code for this.


Cheers
A

hsh = Hash.new{|h,k| h[k]=[]}
keys.zip(values).each{|k,v| hsh[k] << v}
 
A

Arihan Sinha

Thanks for this but I am getting like

[[300, 1], [300, 2], [301, 1], [301, 3], [301, 4], [302, 3], [302, 4]]

but I actually need like

hsh = {"300" =>["1","2"],"301" => ["1","3","4"],"302"=>["3","4"]}

any help
 
M

Mike Stok

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


Thanks for this but I am getting like
=20
[[300, 1], [300, 2], [301, 1], [301, 3], [301, 4], [302, 3], [302, 4]]
=20
but I actually need like
=20
hsh =3D {"300" =3D>["1","2"],"301" =3D> = ["1","3","4"],"302"=3D>["3","4"]}
=20
any help

In ruby 1.9's irb:

ratdog:~ mike$ irb
keys =3D [300,300,301,301,301,302,302] =3D> [300, 300, 301, 301, 301, 302, 302]
values =3D [1, 2, 1, 3, 4, 3, 4] =3D> [1, 2, 1, 3, 4, 3, 4]
hsh =3D Hash.new{ |h, k| h[k] =3D [] } =3D> {}
keys.zip(values) { |k, v| hsh[k] << v } =3D> nil
hsh
=3D> {300=3D>[1, 2], 301=3D>[1, 3, 4], 302=3D>[3, 4]}

Mike

- --=20

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.




-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (Darwin)

iEYEARECAAYFAk1P434ACgkQnsTBwAWZE9q80gCdEdw+bHUgGBNYGKYt4VmHg72R
cI4An0go3pXoDATGibvDOPQO5QdNCRa/
=3D5+ET
-----END PGP SIGNATURE-----
 
R

Robert Klemme

Thanks for this but I am getting like

[[300, 1], [300, 2], [301, 1], [301, 3], [301, 4], [302, 3], [302, 4]]

???

irb(main):004:0> hsh = Hash.new{|h,k| h[k]=[]}
=> {}
irb(main):005:0> keys.zip(values).each{|k,v| hsh[k] << v}
=> [[300, 1], [300, 2], [301, 1], [301, 3], [301, 4], [302, 3], [302, 4]]
irb(main):006:0> hsh
=> {300=>[1, 2], 301=>[1, 3, 4], 302=>[3, 4]}
but I actually need like

hsh = {"300" =>["1","2"],"301" => ["1","3","4"],"302"=>["3","4"]}

Btw, #zip without #each is more efficient:

irb(main):007:0> hsh = Hash.new{|h,k| h[k]=[]}
=> {}
irb(main):008:0> keys.zip(values) {|k,v| hsh[k] << v}
=> nil
irb(main):009:0> hsh
=> {300=>[1, 2], 301=>[1, 3, 4], 302=>[3, 4]}

Cheers

robert
 
A

Alex Gutteridge

Thanks for this but I am getting like

[[300, 1], [300, 2], [301, 1], [301, 3], [301, 4], [302, 3], [302,
4]]

???

irb(main):004:0> hsh = Hash.new{|h,k| h[k]=[]}
=> {}
irb(main):005:0> keys.zip(values).each{|k,v| hsh[k] << v}
=> [[300, 1], [300, 2], [301, 1], [301, 3], [301, 4], [302, 3], [302,
4]]
irb(main):006:0> hsh
=> {300=>[1, 2], 301=>[1, 3, 4], 302=>[3, 4]}
but I actually need like

hsh = {"300" =>["1","2"],"301" => ["1","3","4"],"302"=>["3","4"]}

Btw, #zip without #each is more efficient:

irb(main):007:0> hsh = Hash.new{|h,k| h[k]=[]}
=> {}
irb(main):008:0> keys.zip(values) {|k,v| hsh[k] << v}
=> nil
irb(main):009:0> hsh
=> {300=>[1, 2], 301=>[1, 3, 4], 302=>[3, 4]}

Cheers

robert

Thanks, I never knew #zip took a block argument before.
 
R

Robert Klemme

Thanks, I never knew #zip took a block argument before.

IIRC that was introduced later. If my memory does not fail me
originally Array#zip only returned an Array and block handling (as
well as multiple Array arguments to Array#zip) were added later.

Kind regards

robert
 
B

botp

keys =3D [300,300,301,301,301,302,302]
values =3D [1, 2, =A01, =A03, =A04, =A03, 4]
hsh =3D {"300" =3D>["1","2"],"301" =3D> ["1","3","4"],"302"=3D>["3","4"]}

just joining the fun here.. an inject version

keys.zip(values).inject(Hash.new{|h,k|h[k]=3D[]}) {|hsh,(k,v)|
hsh.tap{|h|h[k] << v}}
#=3D> {300=3D>[1, 2], 301=3D>[1, 3, 4], 302=3D>[3, 4]}

or

keys.zip(values).inject2(Hash.new{|h,k|h[k]=3D[]}) {|h,(k,v)| h[k] << v}
#=3D> {300=3D>[1, 2], 301=3D>[1, 3, 4], 302=3D>[3, 4]}

best regards -botp
 
B

Brian Candler

botp wrote in post #980085:
just joining the fun here.. an inject version

keys.zip(values).inject(Hash.new{|h,k|h[k]=[]}) {|hsh,(k,v)|
hsh.tap{|h|h[k] << v}}
#=> {300=>[1, 2], 301=>[1, 3, 4], 302=>[3, 4]}

That's a prime example of using inject purely for obfuscation.

The principal property of inject is that the value which is the output
of one iteration is fed in as in input to the next iteration. You're not
using that property here, because you're mutating the same object each
time. In that case, it's just a complicated way of saying 'each'. You
may as well just write:

h = Hash.new { |h,k| h[k] = [] }
keys.zip(values).each { |k,v| h[k] << v }
h

Furthermore, if you insist on using #tap, at least do it on the outside
where it belongs in this case:

Hash.new { |h,k| h[k] = [] }.tap do |hsh|
keys.zip(values).each { |k,v| hsh[k] << v }
end

Now, if you wanted to do this in a functional way using inject, then you
would mutate nothing and instead build a new Hash object in each
iteration:

keys.zip(values).inject({}) do |hsh,(k,v)|
if hsh.has_key?(k)
hsh.merge(k=>hsh[k]+[v])
else
hsh.merge(k=>[v])
end
end

That, in my opinion, is the correct way to use inject here - and it's
reasonably clear when written that way too. The Ruby runtime will end up
doing a lot of hash copying though.

Regards,

Brian.
 

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

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,233
Latest member
AlyssaCrai

Latest Threads

Top