Help constructing interesting hash?

C

Chris McMahon

Suppose I have an array of arrays like

[[A, B, C][1,2,3]]

I can easily make a hash (using each_with_index) where one value is
the lookup value for the other value:

1=>A
2=>B
3=>C

Now suppose I have a AoA like

[[A, B, C,][1,2,2]]

Is there a readable way to construct a hash like

1=>[A]
2=>[B, C]

?

Thanks,
-Chris
 
R

Ross Bamford

Suppose I have an array of arrays like

[[A, B, C][1,2,3]]

I can easily make a hash (using each_with_index) where one value is
the lookup value for the other value:

1=>A
2=>B
3=>C

Now suppose I have a AoA like

[[A, B, C,][1,2,2]]

Is there a readable way to construct a hash like

1=>[A]
2=>[B, C]

?

Thanks,
-Chris

I assumed you meant [['A', 'B', 'C'],[1,2,2]] - I know comma at end can be
valid syntax but not sure if it fits here?
If so, this seems to work:

a = [['A', 'B', 'C'],[1,2,2]]

h = {}
a[1].each_with_index { |it, i|
(h[it] ||= []) << a[0]
}

p h # => {1=>["A"], 2=>["B", "C"]}
 
G

gwtmp01

Now suppose I have a AoA like

[[A, B, C,][1,2,2]]

Is there a readable way to construct a hash like

1=>[A]
2=>[B, C]

input = [[:A, :B, :C],[1,2,2]]

output = {}
input[1].each_with_index { |group, index| (output[group] ||= []) <<
input[0][index] }

puts "input: #{input.inspect}"
puts "output: #{output.inspect}"
 
S

Sean O'Halpin

Suppose I have an array of arrays like

[[A, B, C][1,2,3]]

I can easily make a hash (using each_with_index) where one value is
the lookup value for the other value:

1=3D>A
2=3D>B
3=3D>C

Now suppose I have a AoA like

[[A, B, C,][1,2,2]]

Is there a readable way to construct a hash like

1=3D>[A]
2=3D>[B, C]

?

Thanks,
-Chris

Here's another way:

a =3D [['A', 'B', 'C'],[1,2,3]]
h =3D Hash[*a[0].zip(a[1]).flatten]
p h
-- OUTPUT --
{"A"=3D>1, "B"=3D>2, "C"=3D>3}

Regards,

Sean
 
B

Belorion

------=_Part_41394_7580586.1133391949798
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Here's a construct I use quite frequently:

hsh =3D Hash.new{ |hh,kk| hh[kk] =3D Array.new }

What this does is that the default value of hsh[somekey] is a new array.

So, with that, we can do this:

a =3D [['a', 'b', 'c'],[1,2,2]]
hsh =3D Hash.new{ |hh,kk| hh[kk] =3D Array.new }
a[0].each_index{ |ii|
hsh[ a[1][ii] ].push( a[0][ii] )
}
hsh =3D> {1=3D>["a"], 2=3D>["b", "c"]}


Suppose I have an array of arrays like

[[A, B, C][1,2,3]]

I can easily make a hash (using each_with_index) where one value is
the lookup value for the other value:

1=3D>A
2=3D>B
3=3D>C

Now suppose I have a AoA like

[[A, B, C,][1,2,2]]

Is there a readable way to construct a hash like

1=3D>[A]
2=3D>[B, C]

?

Thanks,
-Chris

Here's another way:

a =3D [['A', 'B', 'C'],[1,2,3]]
h =3D Hash[*a[0].zip(a[1]).flatten]
p h
-- OUTPUT --
{"A"=3D>1, "B"=3D>2, "C"=3D>3}

Regards,

Sean

------=_Part_41394_7580586.1133391949798--
 
S

Sean O'Halpin

Oops - I didn't read the full message properly.

Here really is a way to achieve what you're after (though whether it
is readable or not is moot :)

a =3D [['A', 'B', 'C'],[1,2,2]]
h =3D a[1].zip(a[0]).inject(Hash.new{|h, k| h[k] =3D Array.new}) {|h, k|
h[k[0]] << k[1]; h }
p h
-- OUTPUT --
{1=3D>["A"], 2=3D>["B", "C"]}

Regards,

Sean
 
D

David A. Black

Hi --

Suppose I have an array of arrays like

[[A, B, C][1,2,3]]

I can easily make a hash (using each_with_index) where one value is
the lookup value for the other value:

1=>A
2=>B
3=>C

Now suppose I have a AoA like

[[A, B, C,][1,2,2]]

Is there a readable way to construct a hash like

1=>[A]
2=>[B, C]

Here's an inject-based way:

a.zip(b).inject({}) do |hash,(key,value)|
(hash[value] ||= []) << key
hash
end


David
 
L

Laza

Firstly, you can use Array#zip instead of each_with_index:

h = {}
[1,2,3].zip([:a, :b, :c]){|key, value| h[key] = value }

h
=> {1=>:a, 2=>:b, 3=>:c}


Secondly, here is the answer

h = {}
[1, 2, 2].zip([:a, :b, :c]){|key, value|
h[key] ||= []; # if key not defined, make it []
h[key]<<value
}

h
=> {1=>[:a], 2=>[:b, :c]}

You can also combine the two lines in
(h[key] ||= []) << value
 
D

Dave Burt

David said:
a.zip(b).inject({}) do |hash,(key,value)|
(hash[value] ||= []) << key
hash
end

or, using Hash's default initializer:

hash = Hash.new {|h, k| h[k] = [] }
a.zip(b).inject(hash) do |h, (k, v)|
h << k
end

Cheers,
Dave
 
S

Simon Strandgaard

On 11/30/05 said:
I can easily make a hash (using each_with_index) where one value is
the lookup value for the other value:


#invert can sometimes be useful.. but not in this case

Hash[*%w(a b c).zip([1, 2, 2]).flatten].invert
#=3D> {1=3D>"a", 2=3D>"c"}
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top