3

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

4

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)

Sign up to request clarification or add additional context in comments.

Comments

3

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);

1 Comment

Thank you, upvote! Code maniac answer was the neatest in my opinion, so the accepted vote went there, but thanks for you anwer!
2

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);

5 Comments

On side note: can we use concat instead of push so we will need not to spread explicitly
@CodeManiac - concat will create a new array, so the code would create new arrays all over the place. That's why I used push.
@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 ?
@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. :-D
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.