0

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"]]}
Community
  • 1
  • 1
Jasmine Lognnes
  • 6,597
  • 9
  • 38
  • 58
  • @Stefan Yes, that also puzzles me. I can't see why they get swapped either. – Jasmine Lognnes Sep 12 '16 at 13:25
  • 1
    @JasmineLognnes: " I can't see why they get swapped either" - because of the same reason. Code in the two snippets is totally different and does different things. Try some debug printing to see what happens at each line and step. – Sergio Tulentsev Sep 12 '16 at 13:31

2 Answers2

1

Where does the extra array come from?

Here. You're pushing it yourself.

keys2[k] << v.keys

Also, this part is different than what you do in the first snippet. If you're gonna do comparisons, do them right. Minimize differences. If you do the same thing (.each_key, etc.), the structures will be the same.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
1

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"]}
Stefan
  • 109,145
  • 14
  • 143
  • 218