Search code examples
javascriptarraysecmascript-6ecmascript-5

Javascript group by array of objects (complicated objects)


After a lot of tries and search, I couldn't solve my following problem:
I have the following array

[
{text: "text", title: "title", cid: "cid", active: true, nodes: [
  {title: "subTitle", text: "subText", cid: "cid", active: true, nodes: [
    {text:"123", title:"321"}, 
    {text:"456", title:"654"},
    {text:"789", title:"765"}
  ]},
   {title: "subTitle", text: "subText2", cid: "cid2", active: true, nodes: [
    {text:"testText", title:"testTitle1"}, 
    {text:"testText", title:"testTitle2"},
    {text:"testText", title:"testTitle3"}
  ]},
  {title: "subTitle", text: "subText3", cid: "cid3", active: true, nodes: [
    {text:"ycycy", title:"asd"}, 
    {text:"nyd", title:"yf"},
    {text:"xfg", title:"qq"}
  ]},
  {title: "anotherSubTitle", text: "subText4", cid: "cid4", active: true, nodes: [
    {text:"fff", title:"hhh"}, 
    {text:"xxx", title:"sss"},
    {text:"hhh", title:"jjj"}
  ]}
]}
]

I want to reach the following format:

[
{text: "text", title: "title", cid: "cid", active: true, nodes: [
  {title: "subTitle", text: "subText", cid: "cid", active: true, nodes: [
    {text:"123", title:"321"}, 
    {text:"456", title:"654"},
    {text:"789", title:"765"},
    {text:"testText", title:"testTitle1"},
    {text:"testText", title:"testTitle1"},
    {text:"testText", title:"testTitle1"},
    {text:"ycycy", title:"asd"}, 
    {text:"nyd", title:"yf"},
    {text:"xfg", title:"qq"}
  ]},
  {title: "anotherSubTitle", text: "subText4", cid: "cid4", active: true, nodes: [
    {text:"fff", title:"hhh"}, 
    {text:"xxx", title:"sss"},
    {text:"hhh", title:"jjj"}
  ]}
]}
]

I tried array.reduce and to loop through the array but each time I got a wrong result...
Any suggestion plz?


Solution

  • You could take a nested grouping by a property for all levels.

    const
        groupBy = (array, key) => array.reduce((r, { nodes, ...o }) => {
            let temp = r.find(q => q[key] === o[key]);
            if (!temp) r.push(temp = o);
            if (nodes) (temp.nodes ??= []).push(...groupBy(nodes, key));
            return r;
        }, []),
        data = [{ text: "text", title: "title", cid: "cid", active: true, nodes: [{ title: "subTitle", text: "subText", cid: "cid", active: true, nodes: [{ text: "123", title: "321" }, { text: "456", title: "654" }, { text: "789", title: "765" }] }, { title: "subTitle", text: "subText2", cid: "cid2", active: true, nodes: [{ text: "testText", title: "testTitle1" }, { text: "testText", title: "testTitle2" }, { text: "testText", title: "testTitle3" }] }, { title: "subTitle", text: "subText3", cid: "cid3", active: true, nodes: [{ text: "ycycy", title: "asd" }, { text: "nyd", title: "yf" }, { text: "xfg", title: "qq" }] }] }],
        result = groupBy(data, 'title');
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }