I'm trying to get into javascript's built-in reduce
function and with the help of that build objects inside array.
But you can use whatever function or method you want.
Expected output
[
{ 'team1': [14697807552, 6858384], '2021': [14697807552, 6858384], 'pepsi': [null, null], 'cola': [14697807552, 6858384] },
{ 'team2': [10268029152, 6922128], '2021': [10268029152, 6922128], 'pepsi': [null, 4800], 'cola': [10268029152, 6917328] },
]
What I tried to do
I created a function which takes array as an argument and calls reduce for each array's element.
function transform(arr, obj = {}) {
return arr.reduce((acc, item) => {
const newObj = {};
newObj[item.name] = item.metrics;
acc.push(newObj);
if (item.children) {
transform(item.children, newObj);
}
return acc;
}, []);
}
console.log(transform(arr))
<script>
const arr = [{
"name": "team1",
"metrics": [
14697807552,
6858384
],
"children": [{
"name": "2021",
"metrics": [
14697807552,
6858384
],
"children": [{
"name": "pepsi",
"metrics": [
null,
null
]
},
{
"name": "cola",
"metrics": [
14697807552,
6858384
]
}
]
}]
},
{
"name": "team2",
"metrics": [
10268029152,
6922128
],
"children": [{
"name": "2021",
"metrics": [
10268029152,
6922128
],
"children": [{
"name": "pepsi",
"metrics": [
null,
4800
]
},
{
"name": "cola",
"metrics": [
10268029152,
6917328
]
}
]
}]
}
]
</script>
But it gives me output that I don't want:
[
{ team1: [ 14697807552, 6858384 ] },
{ team2: [ 10268029152, 6922128 ] }
]
If you didn't understand my question or you have question, ask me. Thanks for paying attention!
CodePudding user response:
The transform
function doesn't do anything with the second argument obj
, and so when you call transform
recursively, newObj
is not extended: this makes the recursive call losing any desired effect.
Instead of passing that second argument, you could use Object.assign
to collect all objects that come back from recursion, and so merge them into one object:
const convert = arr =>
arr?.map(({name, metrics, children}) =>
Object.assign({[name]: metrics}, ...convert(children))) ?? [];
const arr = [{"name": "team1","metrics": [14697807552,6858384],"children": [{"name": "2021","metrics": [14697807552,6858384],"children": [{"name": "pepsi","metrics": [null,null]},{"name": "cola","metrics": [14697807552,6858384]}]}]},{"name": "team2","metrics": [10268029152,6922128],"children": [{"name": "2021","metrics": [10268029152,6922128],"children": [{"name": "pepsi","metrics": [null,4800]},{"name": "cola","metrics": [10268029152,6917328]}]}]}];
console.log(convert(arr));
Please realise that a property like '2021' is an index and will be ordered before other, non-index properties. Even if you print an object like { 'a': 2, '2021': 1 }
you'll get the keys in opposite order for that same reason.
If the order of the object keys is important to you, then you should go for an array of pairs in stead of a plain object. Arrays are the structure of choice when you need order, and plain objects should be used when order is not essential.
CodePudding user response:
I have found a bit different solution:) It is longer than answer from @trincot but also works
const arr = [{"name": "team1","metrics": [14697807552,6858384],"children": [{"name": "2021","metrics": [14697807552,6858384],"children": [{"name": "pepsi","metrics": [null,null]},{"name": "cola","metrics": [14697807552,6858384]}]}]},{"name": "team2","metrics": [10268029152,6922128],"children": [{"name": "2021","metrics": [10268029152,6922128],"children": [{"name": "pepsi","metrics": [null,4800]},{"name": "cola","metrics": [10268029152,6917328]}]}]}];
const handleArr = (list, rez) => {
list.forEach((item) => {
rez[item.name] = item.metrics;
item.children && handleArr(item.children, rez);
});
};
const handle = (list) => {
const rezArr = [];
for (const item of list) {
const rezObj = { [item.name]: item.metrics };
item.children && handleArr(item.children, rezObj);
rezArr.push(rezObj);
}
return rezArr;
};
console.log(handle(arr));