rj487
rj487

Reputation: 4634

Rails how to group by nested hash

I have no clue to solve this question. I got a nested hash inside an array called data. Here is its structure.

data = 
[
     {
              :id => 1,
            :name => "S1",
        :children => [
            {
                      :id => 10,
                    :name => "S10",
                :children => [
                    {
                          :id => 20,
                        :name => "S20"
                    }
                ]
            }
        ]
    },
     {
              :id => 1,
            :name => "S1",
        :children => [
           {
                      :id => 10,
                    :name => "S10",
                :children => [
                   {
                          :id => 21,
                        :name => "S21"
                    }
                ]
            }
        ]
    },
     {
              :id => 1,
            :name => "S1",
        :children => [
             {
                      :id => 11,
                    :name => "S11",
                :children => [
                     {
                          :id => 22,
                        :name => "S22"
                    }
                ]
            }
        ]
    }
]

As you can see, there are bunch of elements which have the same id in the first layer or second layer, so I need to group them.

I hope the result will be

result=  
[
     {
              :id => 1,
            :name => "S1",
        :children => [
            {
                      :id => 10,
                    :name => "S10",
                :children => [
                    {
                          :id => 20,
                        :name => "S20"
                    },
                    {
                          :id => 21,
                        :name => "S21"
                    }
                ]
            },
            {
                      :id => 11,
                    :name => "S11",
                :children => [
                     {
                          :id => 22,
                        :name => "S22"
                    }
                ]
            }
        ]
    }
]

I've tried somthing like

data.group_by{|s| s[:id]}

However, it would only group the first layer, I don't know how to group nested structure.

Upvotes: 2

Views: 1185

Answers (1)

Ginty
Ginty

Reputation: 3501

Yeah you need some kind of recursive method to recursively combine and group the nested children.

This produces the result you want:

def group(data)
  r = {}
  # Combine the children
  data.each do |d| 
    if r[d[:id]]
      r[d[:id]][:children] += d[:children]
    else
      r[d[:id]] = d
    end
  end
  # Now group the children
  r.values.map do |d|
    d[:children] = group(d[:children]) if d[:children]
    d
  end
end

Upvotes: 4

Related Questions