Jasmine Lognnes - 1 year ago 44

Ruby Question

This question is a continuation of this answer.

Below I am trying to reproduce the answer with the real data structure, but I get an extra array for some reason and the elements are swapped.

**Question**

The two outputs should be the same, so can anyone see what I am doing wrong?

This is correct:

`require 'pp'`

a = {"A"=>1, "B"=>1, "C"=>1}

b = {"A"=>1, "B"=>1, "D"=>1, "E"=>1}

c = {"D"=>1, "E"=>1, "F"=>1}

keys = Hash.new { |hash, key| hash[key] = [] }

a.each_key { |k| keys[k] << :a }

b.each_key { |k| keys[k] << :b }

c.each_key { |k| keys[k] << :c }

pp keys

which gives

`{"A"=>[:a, :b],`

"B"=>[:a, :b],

"C"=>[:a],

"D"=>[:b, :c],

"E"=>[:b, :c],

"F"=>[:c]}

Here is the real data structure,

`groups = {`

"a" => {"A"=>1, "B"=>1, "C"=>1},

"b" => {"A"=>1, "B"=>1, "D"=>1, "E"=>1},

"c" => {"D"=>1, "E"=>1, "F"=>1}

}

keys2 = Hash.new { |hash, key| hash[key] = [] }

groups.each { |k,v| keys2[k] << v.keys }

pp keys2

which gives the incorrect output

`{"a"=>[["A", "B", "C"]], "b"=>[["A", "B", "D", "E"]], "c"=>[["D", "E", "F"]]}`

Answer Source

Since your innermost structure hasn't changed, the `each_key`

part should be almost identical, i.e.:

```
a.each_key { |k| keys[k] << :a }
```

But `a`

now refers to one of your nested hashes and `:a`

to its name:

```
hash.each_key { |k| keys2[k] << name }
```

`name`

and `hash`

refer to the keys and values in `group`

:

```
groups = {
"a" => {"A"=>1, "B"=>1, "C"=>1},
# ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
# name hash
```

(Note that you can pick any variable name, `name`

and `hash`

are just examples.)

Putting it all together:

```
require 'pp'
keys2 = Hash.new { |hash, key| hash[key] = [] }
groups.each do |name, hash|
hash.each_key { |k| keys2[k] << name }
end
pp keys2
```

Output:

```
{"A"=>["a", "b"],
"B"=>["a", "b"],
"C"=>["a"],
"D"=>["b", "c"],
"E"=>["b", "c"],
"F"=>["c"]}
```