Reputation: 1984
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
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
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