1

I have been struggling with a problem that I am trying to solve in a performant and better way. Basically I have a Collection, or in simpler terms an array of objects. I'll paste the collection down:

[
    {
      "pluginId": "fy9h-dKw",
      "pluginVersion": 1,
      "pcVersion": "4.26",
      "platform": "win",
      "previews": [
        {
          "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
        }
      ],
      "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
    },
    {
      "pluginId": "fy9h-dKw",
      "pluginVersion": 1,
      "pcVersion": "4.26",
      "platform": "mac",
      "previews": [
        {
          "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
        }
      ],
      "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
    },
    {
      "pluginId": "fy9h-dKw",
      "pluginVersion": 1,
      "pcVersion": "4.26",
      "platform": "linux",
      "previews": [
        {
          "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
        }
      ],
      "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
    },
    {
      "pluginId": "fy9h-dKw1",
      "pluginVersion": 1,
      "pcVersion": "4.26",
      "platform": "win",
      "previews": [
        {
          "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
        }
      ],
      "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
    },
    {
      "pluginId": "fy9h-dKw1",
      "pluginVersion": 1,
      "pcVersion": "4.26",
      "platform": "mac",
      "previews": [
        {
          "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
        }
      ],
      "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
    },
    {
      "pluginId": "fy9h-dKw1",
      "pluginVersion": 1,
      "pcVersion": "4.26",
      "platform": "linux",
      "previews": [
        {
          "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
        }
      ],
      "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
    },
    {
      "pluginId": "fy9h-dKw2",
      "pluginVersion": 1,
      "pcVersion": "4.26",
      "platform": "win",
      "previews": [
        {
          "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
        }
      ],
      "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
    }
  ]

Now the reason that I want to change it a specific format is that I could use it with a UI library that dictates it to be in a specific format. I'll paste the end result down:

[
{
    "name": "fy9h-dKw", "children": [
        {
            "name": "4.26", "children": [
                {
                    "name": "1", "children": [
                        {
                            "name": "mac", "children": [
                                {
                                    "pluginId": "fy9h-dKw",
                                    "pluginVersion": 1,
                                    "pcVersion": "4.26",
                                    "platform": "mac",
                                    "previews": [
                                        {
                                            "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
                                        }
                                    ],
                                    "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
                                }
                            ],
                            "name": "windows", "children": [
                                {
                                    "pluginId": "fy9h-dKw",
                                    "pluginVersion": 1,
                                    "pcVersion": "4.26",
                                    "platform": "win",
                                    "previews": [
                                        {
                                            "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
                                        }
                                    ],
                                    "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
                                }
                            ],
                            "name": "linux", "children": [
                                {
                                    "pluginId": "fy9h-dKw",
                                    "pluginVersion": 1,
                                    "pcVersion": "4.26",
                                    "platform": "linux",
                                    "previews": [
                                        {
                                            "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
                                        }
                                    ],
                                    "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
                                }
                            ],
                        }
                    ]
                }
            ]
        }
    ]
},
{
    "name": "fy9h-dKw1", "children": [
        {
            "name": "4.26", "children": [
                {
                    "name": "1", "children": [
                        {
                            "name": "mac", "children": [
                                {
                                    "pluginId": "fy9h-dKw1",
                                    "pluginVersion": 1,
                                    "pcVersion": "4.26",
                                    "platform": "mac",
                                    "previews": [
                                        {
                                            "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
                                        }
                                    ],
                                    "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
                                }
                            ],
                            "name": "windows", "children": [
                                {
                                    "pluginId": "fy9h-dKw1",
                                    "pluginVersion": 1,
                                    "pcVersion": "4.26",
                                    "platform": "win",
                                    "previews": [
                                        {
                                            "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
                                        }
                                    ],
                                    "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
                                },

                            ],
                            "name": "linux", "children": [
                                {
                                    "pluginId": "fy9h-dKw1",
                                    "pluginVersion": 1,
                                    "pcVersion": "4.26",
                                    "platform": "linux",
                                    "previews": [
                                        {
                                            "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
                                        }
                                    ],
                                    "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
                                }
                            ],
                        }
                    ]
                }
            ]
        }
    ]
},
{
    "name": "fy9h-dKw2", "children": [
        {
            "name": "4.26", "children": [
                {
                    "name": "1", "children": [
                        {
                            "name": "mac", "children": [
                                {
                                }
                            ],
                            "name": "windows", "children": [
                                {
                                    "pluginId": "fy9h-dKw2",
                                    "pluginVersion": 1,
                                    "pcVersion": "4.26",
                                    "platform": "win",
                                    "previews": [
                                        {
                                            "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg"
                                        }
                                    ],
                                    "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip"
                                }
                            ],
                            "name": "linux", "children": [
                                {
                                }
                            ],
                        }
                    ]
                }
            ]
        }
    ]
}
]

To clear out the confusion with the mess of this end result, all I want is to group them by their pluginId, then by their pcVersion, then by their pluginVersion, and in end by their platform. I'll just paste the format of end result:

[
{
    "name": "pluginId", "children": [
        {
            "name": "pcVersion", "children": [
                {
                    "name": "pluginVersion", "children": [
                        {
                            "name": "mac", "children": [
                                {
                                }
                            ],
                            "name": "windows", "children": [
                                {
                                }
                            ],
                            "name": "linux", "children": [
                                {
                                }
                            ],
                        }
                    ]
                }
            ]
        }
    ]
}
]

I found out about the Lodash Library groupBy method that is excellent. But I have to write a lot of bad loops for it and its too complicated.

I would really appreciate any hints or leads to solve it as I have been stuck on it for a lo\t of hours now and getting extremely frustrated. Thanks in advance.

1 Answer 1

2

Here is a fairly compact example using nested reduce() calls and passing an array of keys describing the hierarchy to the inner reduce(). This allows you to refactor the original array in multiple ways simply by passing a different hierarchy array.

const srcArr = [{ "pluginId": "fy9h-dKw", "pluginVersion": 1, "pcVersion": "4.26", "platform": "win", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw", "pluginVersion": 1, "pcVersion": "4.26", "platform": "mac", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw", "pluginVersion": 1, "pcVersion": "4.26", "platform": "linux", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw1", "pluginVersion": 1, "pcVersion": "4.26", "platform": "win", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw1", "pluginVersion": 1, "pcVersion": "4.26", "platform": "mac", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw1", "pluginVersion": 1, "pcVersion": "4.26", "platform": "linux", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw2", "pluginVersion": 1, "pcVersion": "4.26", "platform": "win", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }]

function refactorArray(arr, tree) {
  return arr.reduce((a, o) => {
    const inner = tree.reduce((ka, k) => {
      const match = ka.find(e => e.name === o[k]);
      if (match) {
        ka = match.children;
      } else {
        const n = { name: o[k], children: [] };
        ka.push(n);
        ka = n.children;
      }
      return ka;
    }, a);
    inner.push({ ...o });
    return a;
  }, []);
}

const tree1 = [
  'pluginId',
  'pcVersion',
  'pluginVersion',
  'platform'];

console.log(refactorArray(srcArr, tree1));
  
const tree2 = [
  'platform', 
  'pluginVersion'];

console.log(refactorArray(srcArr, tree2));

Or using bind() to create dedicated functions...

const srcArr = [{ "pluginId": "fy9h-dKw", "pluginVersion": 1, "pcVersion": "4.26", "platform": "win", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw", "pluginVersion": 1, "pcVersion": "4.26", "platform": "mac", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw", "pluginVersion": 1, "pcVersion": "4.26", "platform": "linux", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw1", "pluginVersion": 1, "pcVersion": "4.26", "platform": "win", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw1", "pluginVersion": 1, "pcVersion": "4.26", "platform": "mac", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw1", "pluginVersion": 1, "pcVersion": "4.26", "platform": "linux", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }, { "pluginId": "fy9h-dKw2", "pluginVersion": 1, "pcVersion": "4.26", "platform": "win", "previews": [{ "uri": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.jpg" }], "pluginUrl": "/e2d4-dKv/4.26/1/7f4bc5e9-3721-4f83-abd4-75792ae75e3d.zip" }]

function refactorArrayByBoundTree(arr) {
  return arr.reduce((a, o) => {
    const inner = this.reduce((ka, k) => {
      const match = ka.find(e => e.name === o[k]);
      if (match) {
        ka = match.children;
      } else {
        const n = { name: o[k], children: [] };
        ka.push(n);
        ka = n.children;
      }
      return ka;
    }, a);
    inner.push({ ...o });
    return a;
  }, []);
}

const tree1 = [
  'pluginId',
  'pcVersion',
  'pluginVersion',
  'platform'];

const refactorByTree1 = refactorArrayByBoundTree.bind(tree1);
console.log(refactorByTree1(srcArr));
  
const tree2 = [
  'platform', 
  'pluginVersion'];

const refactorByTree2 = refactorArrayByBoundTree.bind(tree2);
console.log(refactorByTree2(srcArr));

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so so much @pilchard. It serves all my need with so much elegancy. You are a saint. Now I am having a bit difficulty understanding it as reduce is a new idea but its compactness has blew me away. I hope you won't mind me bothering you a couple of times about it in the comment section. Cheers!!!
Glad it works for you. Feel free to ask questions, I'm happy to help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.