5

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.

3
  • titles should be array if there is only one record? Commented Jul 18, 2016 at 13:59
  • 1
    is the property really 'title:'? Commented Jul 18, 2016 at 15:03
  • @NinaScholz.. well spotted Commented Jul 18, 2016 at 16:25

3 Answers 3

9

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();
Sign up to request clarification or add additional context in comments.

1 Comment

You have missing the .value() resolver to resolve the chain, otherwise you'll get a LodashWrapper instead of the needed value, +1 for the nice approach
3

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

3 Comments

Isn't this the same answer? You added an arrow function to the solution, but otherwise only the second part of your answer is new.
@4castle actually I didn't check yours, but your original answer was a little different, (I think u've used _.chain), even now your's is not correct, since you have missing the .value() resolver at the end
It's working correctly, but I was also under the impression that .value() was only needed if .chain() was used. That's why I switched to the constructor.
2

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

1 Comment

Thank you, although a lodash example would be great. Just to keep it brief.

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.