Lodash create collection from duplicate object keys
I have the following structure:
var output = [{
"article": "BlahBlah",
"title": "Another blah"
}, {
"article": "BlahBlah",
"title": "Return of the blah"
}, {
"article": "BlahBlah2",
"title": "The blah strikes back"
}, {
"article": "BlahBlah2",
"title": "The blahfather"
}]
From the above using an elegant lodash one-liner, I need to create the following structure.
var newOutput = [{
"article": "BlahBlah",
"titles": ["Another blah", "Return of the blah"]
}, {
"article": "BlahBlah2",
"titles": ["The blah strikes back", "The blahfather"]
}]
Help as always, is greatly appreciated.. A huge plus for an explanation for how a solution would work.
Use _.groupBy
and then _.map
the resulting object to an array of objects.
var newOutput = _(output)
.groupBy('article')
.map(function(v, k){ return { article: k, titles: _.map(v, 'title') } })
.value();
var output = [{"article":"BlahBlah","title":"Another blah"},{"article":"BlahBlah","title":"Return of the blah"},{"article":"BlahBlah2","title":"The blah strikes back"},{"article":"BlahBlah2","title":"The blahfather"}];
let newOutput = _(output)
.groupBy('article')
.map(function(v, k){ return { article: k, titles: _.map(v, 'title') } })
.value();
console.log(newOutput);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>
With ES6 arrow-functions,
var newOutput = _(output)
.groupBy('article')
.map((v, k) => ({ article: k, titles: _.map(v, 'title') }))
.value();
A better lodash version could be (using the awesome chaining
approach)
_(a).groupBy('article').map( (x,k) => ({ article: k, titles:_.map(x, 'title')}) ).value();
If you want to group by article (so article would be the key, useful for quick lookup)
_(a).groupBy('article').mapValues(x => _.map(x, 'title')).value();
A proposal in plain Javascript
It uses a IIFE (Immediate Invoked Function Expression) for using private variables and for collecting the return values in an array.
Beside that it uses a hash table for the reference to the right array item.
var output = [{ article: "BlahBlah", title: "Another blah" }, { article: "BlahBlah", title: "Return of the blah" }, { article: "BlahBlah2", title: "The blah strikes back" }, { article: "BlahBlah2", title: "The blahfather" }],
newOutput = function (data) {
var r = [];
data.forEach(function (a) {
if (!this[a.article]) {
this[a.article] = { article: a.article, titles: [] };
r.push(this[a.article]);
}
this[a.article].titles.push(a.title);
}, Object.create(null));
return r;
}(output);
console.log(newOutput);