Consider I have two helper functions that can transform a flat array of {} into a tree-like structure. Let's analyze the following flat data:
const data = [
{
"ID": 1,
"Tier_1": "DataSource1",
"Tier_2": "Area",
"Tier_3": "General",
},
{
"ID": 2,
"Tier_1": "DataSource1",
"Tier_2": "Financial",
"Tier_3": "General",
},
{
"ID": 3,
"Tier_1": "DataSource1",
"Tier_2": "Area",
"Tier_3": "General",
},
{
"ID": 4,
"Tier_1": "DataSource2",
"Tier_2": "Area",
"Tier_3": "General",
},
{
"ID": 5,
"Tier_1": "DataSource2",
"Tier_2": "Area",
"Tier_3": "Management Plan",
}
]
This data holds hierarchical information in three rows, ready to be converted into a tree structure. Here is the expected output:
(The last children represent actual DB objects, distributed within the tree)
const output = {
"DataSource1: {
"Area": {
{
"ID": 1,
"Tier_1": "DataSource1",
"Tier_2": "Area",
"Tier_3": "General",
},
{
"ID": 3,
"Tier_1": "DataSource1",
"Tier_2": "Area",
"Tier_3": "General",
},
},
"Financial": [
{
"ID": 2,
"Tier_1": "DataSource1",
"Tier_2": "Financial",
"Tier_3": "General",
},
]
},
"DataSource2: {
"Area": [
{
"ID": 4,
"Tier_1": "DataSource2",
"Tier_2": "Area",
"Tier_3": "General",
},
{
"ID": 5,
"Tier_1": "DataSource2",
"Tier_2": "Area",
"Tier_3": "Management Plan",
}
]
}
}
}
I've already created functions for this purpose, but they lack flexibility (as the depth / dimensions are fixed and specified in each function name).
Here is the function that returns a 2-dimensional tree:
const getDataCategoriesTwoDim = (data, mainCategory) => {
const dataFields = [...data];
let map = {};
for (let i = 0; i < dataFields.length; i += 1) {
const currentField = dataFields[i];
const currentCategory = currentField[mainCategory];
if (!map[currentCategory]) {
map[currentCategory] = [];
}
map[currentCategory].push(currentField);
}
return map;
};
And here is the function that returns a three-dimensional tree:
const getDataCategoriesThreeDim = (data, mainCategory, subCategory) => {
const dataFields = [...data];
let map = {};
for (let i = 0; i < dataFields.length; i += 1) {
const currentField = dataFields[i];
const currentCategory = currentField[mainCategory];
const currentSubcategory = currentField[subCategory];
if (!map[currentCategory]) {
map[currentCategory] = {};
}
if (!map[currentCategory][currentSubcategory]) {
map[currentCategory][currentSubcategory] = [];
}
map[currentCategory][currentSubcategory].push(currentField);
}
return map;
};
You can call both functions as follows to achieve the desired outcome:
getDataCategoriesTwoDim(data, 'Tier_2');
getDataCategoriesThreeDim(data, 'Tier_2', 'Tier_3');
The code has noticeable repetition and copy-pasting. The variations between the functions are marked in comments. How can I refactor the code into one versatile function that allows me to set 2, 3 or more dimensions?