I have a multidimentionnal array and i want to rename property recursevly, i've tried this function
const newMenu =
Array.isArray(copyMenu) &&
copyMenu.length > 0 &&
copyMenu.map(({ families: children, id: key, label: title, ...rest }) => ({
key,
title,
...rest,
children,
}));
But it rename just the big array, not the properties inside table property This is my input array :
const input = [
{
id: 9040,
label: "33",
tables: [
{
id: 8957,
label: "THB_Adresse_Famille",
idFather: 8957,
tableIsFamily: false,
tables: []
},
{
id: 8941,
label: "THB_Contact_Famille",
idFather: 8941,
tableIsFamily: false,
tables: [
{ id: 8947, label: "THB_Contact_Table", idFather: 8941 },
{ id: 9855, label: "THB_Contact_Table_BIS", idFather: 8941 }
]
},
{
id: 8949,
label: "THB_Societe_Famille",
idFather: 8949,
tableIsFamily: false,
tables: []
},
{
id: 8983,
label: "THB_TELEPHONE",
idFather: 8983,
tableIsFamily: false,
tables: []
},
{
id: 10070,
label: "THB_TEST_5708",
idFather: 10070,
tableIsFamily: false,
tables: []
}
]
},
{
id: 9761,
label: "1111111",
tables: [
{
id: 9742,
label: "RRA PROTOCOLE",
idFather: 9742,
tableIsFamily: false,
tables: []
},
{
id: 9753,
label: "RRA TEST CASE LINE",
idFather: 9753,
tableIsFamily: false,
tables: []
}
]
},
]
The output should be ike this :
const output = [
{
key: 9040,
title: "33",
children: [
{
key: 8957,
title: "THB_Adresse_Famille",
idFather: 8957,
tableIsFamily: false,
children: []
},
{
key: 8941,
title: "THB_Contact_Famille",
idFather: 8941,
tableIsFamily: false,
children: [
{ key: 8947, title: "THB_Contact_Table", idFather: 8941 },
{ key: 9855, title: "THB_Contact_Table_BIS", idFather: 8941 }
]
},
{
key: 8949,
title: "THB_Societe_Famille",
idFather: 8949,
tableIsFamily: false,
children: []
},
{
key: 8983,
title: "THB_TELEPHONE",
idFather: 8983,
tableIsFamily: false,
children: []
},
{
key: 10070,
title: "THB_TEST_5708",
idFather: 10070,
tableIsFamily: false,
children: []
}
]
},
{
key: 9761,
title: "1111111",
children: [
{
key: 9742,
title: "RRA PROTOCOLE",
idFather: 9742,
tableIsFamily: false,
children: []
},
{
key: 9753,
title: "RRA TEST CASE LINE",
idFather: 9753,
tableIsFamily: false,
children: []
}
]
},
]
I'v searched on stackoverflow but i don't found any solutions to this case, any help will be appreciated. Thank you
CodePudding user response:
You can use recursive approach to rename your keys by maintaining a lookup for renamed keys and recursively calling your function for array values.
const input = [ { id: 9040, label: "33", tables: [ { id: 8957, label: "THB_Adresse_Famille", idFather: 8957, tableIsFamily: false, tables: [] }, { id: 8941, label: "THB_Contact_Famille", idFather: 8941, tableIsFamily: false, tables: [ { id: 8947, label:"THB_Contact_Table", idFather: 8941 }, { id: 9855, label: "THB_Contact_Table_BIS", idFather: 8941 } ] }, { id: 8949, label: "THB_Societe_Famille", idFather: 8949, tableIsFamily: false, tables: [] }, { id: 8983, label: "THB_TELEPHONE", idFather: 8983, tableIsFamily: false, tables: [] }, { id: 10070, label: "THB_TEST_5708", idFather: 10070, tableIsFamily: false, tables: [] } ] }, { id: 9761, label: "1111111", tables: [ { id: 9742, label: "RRA PROTOCOLE", idFather: 9742, tableIsFamily: false, tables: [] }, { id: 9753, label: "RRA TEST CASE LINE", idFather: 9753, tableIsFamily: false, tables: [] } ] }, ],
keys = { id: 'key', label: 'title', tables: 'children'},
rename = (arr) => {
return arr.map(o => {
return Object.fromEntries(Object.keys(o).map(k => {
const key = keys[k] || k;
const value = Array.isArray(o[k]) ? rename(o[k]) : o[k];
return [key, value];
}));
});
};
console.log(rename(input));
CodePudding user response:
I see your attempted solution is lacking the recursive call you say you want to implement. It may be a little tricky to conceive. You essentially need to wrap the repeating code in a function.
const recurse = (input) =>
input?.map(({ tables, id, label, ...rest }) =>
({ children: recurse(tables), key: id, title: label, ...rest }))
Then, notice the function calls itself on the relevant part, a.k.a. the general case. Also not unimportantly, the function needs to know when to stop, i.e. when it has hit the base case. Without checking for the base case you will quickly find out where this website gets its name from. In the example above I did apply optional chaining so it is a bit subtle.
Edit: with regard to destructuring, there are roughly two equivalent approaches (as far as I can see), here is the other which matches more with your initial approach:
const recurse = (input) =>
input?.map(({ tables, id: key, label: title, ...rest }) =>
({ children: recurse(tables), key, title, ...rest }))
CodePudding user response:
A potential solution could be:
const input = [{
id: 9040,
label: "33",
tables: [{
id: 8957,
label: "THB_Adresse_Famille",
idFather: 8957,
tableIsFamily: false,
tables: []
},
{
id: 8941,
label: "THB_Contact_Famille",
idFather: 8941,
tableIsFamily: false,
tables: [{
id: 8947,
label: "THB_Contact_Table",
idFather: 8941
},
{
id: 9855,
label: "THB_Contact_Table_BIS",
idFather: 8941
}
]
},
{
id: 8949,
label: "THB_Societe_Famille",
idFather: 8949,
tableIsFamily: false,
tables: []
},
{
id: 8983,
label: "THB_TELEPHONE",
idFather: 8983,
tableIsFamily: false,
tables: []
},
{
id: 10070,
label: "THB_TEST_5708",
idFather: 10070,
tableIsFamily: false,
tables: []
}
]
},
{
id: 9761,
label: "1111111",
tables: [{
id: 9742,
label: "RRA PROTOCOLE",
idFather: 9742,
tableIsFamily: false,
tables: []
},
{
id: 9753,
label: "RRA TEST CASE LINE",
idFather: 9753,
tableIsFamily: false,
tables: []
}
]
},
];
function updateKeys(arr) {
return arr.map(({
tables,
id: key,
label: title,
...rest
}) => {
const children = Array.isArray(tables) && tables.length > 0 ? updateKeys(tables) : tables;
return {
key,
title,
children,
...rest
}
});
}
const output = updateKeys(input);
console.log(output);
CodePudding user response:
Looks like a number of good answers have been provided. Here's one potential implementation to achieve the desired objective:
Sample Code
const replacePropsMap = {
id: 'key',
label: 'title',
tables: 'children'
};
const renameProps = (arr = inputArr, propsMap = replacePropsMap) => (
arr.reduce((fin, itm) => ([
...fin,
{
...(
Object.entries(itm).reduce((fin2, itm2) => ({
...fin2,
...(
itm2[0] in propsMap
? { [propsMap[itm2[0]]]: itm2[1] }
: {}
)
}), {})
),
children: itm && itm.tables && itm.tables.length > 0
? renameProps(itm.tables)
: []
}
]), [])
);
Explanation
- Use
.reduceto iterate through the array (with the aggregator asfinand each item asitm) - Use
...spread-operator to first place existing items (from past iterations) - Next, for current
itm, useObject.entries()and.reduceto filter-outid,label,tablesprops, but retain all other props - Use
key,titleto hold values ofid,labelrespectively - Recurse the above for the
tablesarray (if it exists) and store the result inchildrenprop.
Code Snippet
const inputArr = [{
id: 9040,
label: "33",
tables: [
{
id: 8957,
label: "THB_Adresse_Famille",
idFather: 8957,
tableIsFamily: false,
tables: []
},
{
id: 8941,
label: "THB_Contact_Famille",
idFather: 8941,
tableIsFamily: false,
tables: [
{ id: 8947, label: "THB_Contact_Table", idFather: 8941 },
{ id: 9855, label: "THB_Contact_Table_BIS", idFather: 8941 }
]
},
{
id: 8949,
label: "THB_Societe_Famille",
idFather: 8949,
tableIsFamily: false,
tables: []
},
{
id: 8983,
label: "THB_TELEPHONE",
idFather: 8983,
tableIsFamily: false,
tables: []
},
{
id: 10070,
label: "THB_TEST_5708",
idFather: 10070,
tableIsFamily: false,
tables: []
}
]
}, {
id: 9761,
label: "1111111",
tables: [
{
id: 9742,
label: "RRA PROTOCOLE",
idFather: 9742,
tableIsFamily: false,
tables: []
},
{
id: 9753,
label: "RRA TEST CASE LINE",
idFather: 9753,
tableIsFamily: false,
tables: []
}
]
}
];
const replacePropsMap = {
id: 'key',
label: 'title',
tables: 'children'
};
const renameProps = (arr = inputArr) => (
arr.reduce((fin, itm) => ([
...fin,
{
...(
Object.entries(itm).reduce((fin2, itm2) => ({
...fin2,
...(
itm2[0] in replacePropsMap
? { [replacePropsMap[itm2[0]]]: itm2[1] }
: {}
)
}), {})
),
children: itm && itm.tables && itm.tables.length > 0
? renameProps(itm.tables)
: []
}
]), [])
);
console.log(renameProps());
