user385729
user385729

Reputation: 1984

Flatten an array of objects to an array of one object by reduce

I want to convert:

[ { foo: 'media' }, { article: 'article' } ]

to:

[{foo: 'media', article: 'article'}]

I tried :

var newdata=[ { foo: 'media' }, { article: 'article' } ].reduce(function(p, c, i, array) {   
  return p[Object.keys(c)[0]]=c[Object.keys(c)[0]]
}, {});

but it returns "article" am I doing something wrong?

Upvotes: 0

Views: 74

Answers (2)

Felix Kling
Felix Kling

Reputation: 816312

am I doing something wrong

Most likely, since you are not getting the result you want.

An assignment expression results in the value that was assigned:

foo = 'bar';
// returns 'bar';

Now, the return value of the callback becomes the input for the next iteration of the callback. But you don't want to pass the assigned value to the next iteration of reduce though, because that would result in the following reduction:

// 1. iteration
p = {}, c = { foo: 'media' }

// 2. iteration
p = 'media', c = { article: 'article' }

// result
'article'

Instead, you want:

// 1. iteration
p = {}, c = { foo: 'media' }

// 2. iteration
p = { foo: 'media' }, c = { article: 'article' }

// result
{ foo: 'media', article: 'article' }

In order to achieve that, you have to return p from the callback, so that in every iteration, the property and its value can be added to it.

You could leverage the comma operator to get a one-liner:

return (p[Object.keys(c)[0]] = c[Object.keys(c)[0]]), p;
//                                                  ^^^

This will assign the property and return p. But better would be

var key = Object.keys(c)[0];
p[key] = c[key];
return p;

Upvotes: 0

Tim van der Lippe
Tim van der Lippe

Reputation: 768

Reduce expects you to return the partical result back in order to iterate over following items. Therefore the following code would work:

var newdata=[ { foo: 'media' }, { article: 'article' } ].reduce(function(p, c, i, array) {   
  // Add item to the array
  p[Object.keys(c)[0]]=c[Object.keys(c)[0]];
  // And return back the object to reduce into
  return p;
}, {});

which outputs:

> newdata
Object {foo: "media", article: "article"}

Upvotes: 6

Related Questions