I have JSON object like this:
[{
"name" : "cat",
"value" : 17,
"group" : "animal",
},
{
"name" : "dog",
"value" : 6,
"group" : "animal",
},
{
"name" : "snak",
"value" : 2,
"group" : "animal",
},
{
"name" : "tesla",
"value" : 11,
"group" : "car",
},
{
"name" : "bmw",
"value" : 23,
"group" : "car",
}]
I want to convert this JSON to below format by JS:
[{
"name":"animal",
"children":[
{"name":"cat", "value":17},
{"name":"dog", "value":6},
{"name":"snak", "value":2}
]},
{
"name":"car",
"children":[
{"name":"bmw", "value":11},
{"name":"tesla", "value":23}
]}]
I try to convert and filter by Reduce
function but I couldn't convert to this format.
EDIT:
The code I tested was this.
let groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
let groubedByExchange=groupBy(JSON_data, 'group');
You could build an array and search for the same group in the array.
var array = [{ name: "cat", value: 17, group: "animal" }, { name: "dog", value: 6, group: "animal" }, { name: "snak", value: 2, group: "animal" }, { name: "tesla", value: 11, group: "car" }, { name: "bmw", value: 23, group: "car" }],
result = array.reduce((r, { group: name, ...object }) => {
var temp = r.find(o => o.name === name);
if (!temp) r.push(temp = { name, children: [] });
temp.children.push(object);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A simple solution is to build an intermediate dictonary and then transform it to your output structure.
You can use Array.reduce()
, Object.entries()
and Array.map()
to do it:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) => {
acc[group] = (acc[group] || []);
acc[group].push({ name, value });
return acc;
}, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
Using the spread operator makes it one line shorter and still readable:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) => {
acc[group] = [...(acc[group] || []), { name, value }];
return acc;
}, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
And one liner shorter with the comma operator:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) =>
(acc[group] = [...(acc[group] || []), { name, value }], acc)
, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
The same can be done with Object.assign()
:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) =>
Object.assign(acc, { [group]: [...(acc[group] || []), { name, value }] })
, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
And finally, a bit longer but with a reusable groupBy
function:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const groupBy = prop => data => {
return data.reduce((dict, item) => {
const { [prop]: _, ...rest } = item;
dict[item[prop]] = [...(dict[item[prop]] || []), rest];
return dict;
}, {});
};
const result = Object.entries(groupBy('group')(data))
.map(([key, value]) => ({ name: key, children: value }));
console.log(result);
Using Array#from, Array#reduce, Array#concat, destructuring, spread syntax and Map.
const data=[{"name":"cat","value":17,"group":"animal",},{"name":"dog","value":6,"group":"animal",},{"name":"snak","value":2,"group":"animal",},{"name":"tesla","value":11,"group":"car",},{"name":"bmw","value":23,"group":"car",}];
const res = Array.from(
data.reduce((a,{group, ...rest})=>{
return a.set(group, [rest].concat(a.get(group)||[]));
}, new Map())
).map(([group, children])=>({group,children}));
console.log(res);
const arr = [{
"name": "cat",
"value": 17,
"group": "animal",
},
{
"name": "dog",
"value": 6,
"group": "animal",
},
{
"name": "snak",
"value": 2,
"group": "animal",
},
{
"name": "tesla",
"value": 11,
"group": "car",
},
{
"name": "bmw",
"value": 23,
"group": "car",
}
]
const newFormat = arr.reduce((pre, cur) => {
const group = pre.find(grp => grp.name === cur.group)
if (group) {
group.children.push({
name: cur.name,
value: cur.value
})
return pre
}
const newGroup = {
name: cur.group,
children: [{
name: cur.name,
value: cur.value
}]
}
pre.push(newGroup)
return pre
}, [])
console.log(newFormat)
there you go. first you try to find that group in new array, if it exists you add that child to it. if not, you create the group and children array and push it to the array
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With