I have data like so:
data = [
{
"foo": {"name":"foo-name"},
"bar": {"name":"bar-name"}
},
{
"baz": {"name":"baz-name"}
}
]
and my desired output would be:
[
{ "foo": {"name":"foo-name"}},
{ "bar": {"name":"bar-name"}},
{ "baz": {"name":"baz-name"}}
]
How do I get this structure? I tried using concat, but realized that it doesn't work as we are dealing with nested objects and not nested arrays. Then I tried iterating in different ways, but not achieving what I want. One try was the following:
const newData = data.map((x) => {
return Object.keys(x).map(el => {
return {[el]: x};
})
})
But that just made it more nested.
3 Answers 3
You can use flatMap
let data = [{"foo": {"name":"foo-name"},"bar": {"name":"bar-name"}},{"baz": {"name":"baz-name"}}]
let final = data.flatMap(a => Object.entries(a).map(([k, v]) => ({
[k]: v
})))
console.log(final)
answered Aug 31, 2019 at 10:26
Code Maniac
37.9k5 gold badges44 silver badges65 bronze badges
Sign up to request clarification or add additional context in comments.
Comments
One option is to reduce into an array, iterating over the entries of each object and pushing them to the accumulator:
const data = [
{
"foo": {"name":"foo-name"},
"bar": {"name":"bar-name"}
},
{
"baz": {"name":"baz-name"}
}
];
const output = data.reduce((a, obj) => {
Object.entries(obj).forEach(([key, val]) => {
a.push({ [key]: val });
});
return a;
}, []);
console.log(output);
answered Aug 31, 2019 at 10:20
CertainPerformance
374k55 gold badges354 silver badges359 bronze badges
1 Comment
DRNR
Thank you, upvote! Code maniac answer was the neatest in my opinion, so the accepted vote went there, but thanks for you anwer!
I'd use a simple for-of with Object.entries mapped to objects:
const result = [];
for (const obj of data) {
result.push(
...Object.entries(obj).map(
([key, value]) => ({[key]: value})
)
);
}
Live Example:
const data = [
{
"foo": {"name":"foo-name"},
"bar": {"name":"bar-name"}
},
{
"baz": {"name":"baz-name"}
}
];
const result = [];
for (const obj of data) {
result.push(
...Object.entries(obj).map(
([key, value]) => ({[key]: value})
)
);
}
console.log(result);
answered Aug 31, 2019 at 10:31
T.J. Crowder
1.1m201 gold badges2k silver badges2k bronze badges
5 Comments
Code Maniac
On side note: can we use
concat instead of push so we will need not to spread explicitlyT.J. Crowder
@CodeManiac -
concat will create a new array, so the code would create new arrays all over the place. That's why I used push.Code Maniac
@T.J.Crowder oh yeah makes sense, maybe a off topic question, since JS have GC does this affect much creating a new array every time vs pushing values to the same array everytime ?
T.J. Crowder
@CodeManiac - Creates memory pressure, which can be a source of performance issues. But of course, it depends on whether this code is run one-off or lots. Odds are pretty high that it wouldn't matter. Also note that the above in theory involves creating an object (the iterator) in order to spread out the array for
push, so it would seem to be a zero-sum equation (create array or create iterator) -- except that JavaScript engines optimize away that iterator when they can (as above). If I were really concerned and didn't know that, I'd use result.push.apply(result, /*...*/) instead. :-DT.J. Crowder
This
push solution is also only valid for arrays up to about 30k entries. (I'm assuming the OP's object doesn't have more than 30k properties.) After which, you run out of stack on V8.lang-js