1

Possible Duplicate:
Merging deep hash in ruby

So I have a hash with the following structure (exploded out to YAML for viewing), that I want to merge/consolidate/flatten down by the very first key.

- 1001: 
    Twitter: 
      values: 
        "2012-11-29": 24.0
- 1001: 
    Linkedin: 
      values: 
        "2012-11-29": 25.0
- 1001: 
    Facebook: 
      values: 
        "2012-11-29": 6.0

- 2002: 
    Twitter: 
      values: 
        "2012-11-29": 26.0
- 2002: 
    Pinterest: 
      values: 
        "2012-11-29": 1.0

That I want to get it down to the following form as easily as possible:

- 1001
   Twitter:
     values:
       #some values here
   Facebook:
     values:
       #some values
- 2002
   Pinterest:
     values:
   Facebook:
     values:

I've tried zipping, merging, splating the Hashes every way I know how, but the best I can get is a new Hash that discards all but the first 2nd-level value it finds.

Any ideas?

Community
  • 1
  • 1
thoughtpunch
  • 1,907
  • 4
  • 25
  • 41
  • Thanks Alex. Still need to know how to merge a whole bunch of hashes with each other? (i.e. not just a.deep_merge(b), but [a,b,c,d].deep_merge) – thoughtpunch Dec 05 '12 at 19:13

1 Answers1

2

Here is a quick workaround.

Initial Hash:

  [
    [0] {
        1001 => {
            "Twitter" => {
                "values" => {
                    "2012-11-29" => 24.0
                }
            }
        }
    },
    [1] {
        1001 => {
            "Linkedin" => {
                "values" => {
                    "2012-11-29" => 25.0
                }
            }
        }
    },
    [2] {
        1001 => {
            "Facebook" => {
                "values" => {
                    "2012-11-29" => 6.0
                }
            }
        }
    },
    [3] {
        2002 => {
            "Twitter" => {
                "values" => {
                    "2012-11-29" => 26.0
                }
            }
        }
    },
    [4] {
        2002 => {
            "Pinterest" => {
                "values" => {
                    "2012-11-29" => 1.0
                }
            }
        }
    }
]

Using inject to merge it:

hash = hash.inject({}) {|f,c| k,v = c.first; (f[k] ||= []) << v; f }

Obtaining this:

{
    1001 => [
        [0] {
            "Twitter" => {
                "values" => {
                    "2012-11-29" => 24.0
                }
            }
        },
        [1] {
            "Linkedin" => {
                "values" => {
                    "2012-11-29" => 25.0
                }
            }
        },
        [2] {
            "Facebook" => {
                "values" => {
                    "2012-11-29" => 6.0
                }
            }
        }
    ],
    2002 => [
        [0] {
            "Twitter" => {
                "values" => {
                    "2012-11-29" => 26.0
                }
            }
        },
        [1] {
            "Pinterest" => {
                "values" => {
                    "2012-11-29" => 1.0
                }
            }
        }
    ]
}

Working Demo

  • Holy crap, that's exactly what I needed! Let me see if I understand what this did correctly: "for each k,v, take first nested hash.Setup a new hash the first key as it's key, and dump any values into new hash". Sound right? – thoughtpunch Dec 05 '12 at 19:18
  • Yep, for each key in orig hash it creates an array containing any hashes with same key –  Dec 05 '12 at 19:23