Grouping an array by postId and userId

I've got this kind of data:

[
{ userId: 1, postId: 1, ... },
{ userId: 1, postId: 2, ... },
{ userId: 2, postId: 3, ... },
...
]


And I need to group them by postId and userId like this:

{
1: { 1: [{ ... }], 2: [{ ... }], ...},
2: { 3: [{ ... }], ...},
...
}


Here is what I've done so far:

var posts = {};
_.forEach(response.posts, function (post) {
if (!posts[post.userId]) {
posts[post.userId] = {};
}
if (!posts[post.userId][post.postId]) {
posts[post.userId][post.postId] = [];
}

posts[post.userId][post.postId].push(post);
});


Any suggestion is welcome (a functional way of doing it using lodash would be great)!

As you noted, a more functional solution could be better. Here is a way to write it using :

var data = [
{ userId: 1, postId: 1, postData: "first post first user" },
{ userId: 1, postId: 2, postData: "second post first user" },
{ userId: 2, postId: 3, postData: "first post second user" }
];

posts = _
.chain(data)
.groupBy('userId')
.mapValues(function(x) {
return _.extend.apply(this, _.map(x, function (y) {
return {[y.postId]: y.postData };
}));
})
.value();


The .groupBy('userId') makes the intention clearer, but whether it is a better solution than the original is debatable. Therefore, you may be better off leaving the code as it is.

• I see. The original poster asked for a lodash solution so maybe I don't understand how you'd do that without posting a solution. But anyway I understand there are norms. – Justin L. Jan 21 '16 at 1:50
• I don't mean to be disagreeable (really), but what my post was actually trying to illustrate is that the original post is probably the better solution to the lodash solution that the poster asked for (and my post it says that in fewer words). You can see for yourself that the iterative solution is straightforward and the lodash solution is awkward, which was the point. – Justin L. Jan 21 '16 at 2:01
• You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and how it improves upon the original) so that the author can learn from your thought process. – Quill Jan 21 '16 at 3:47
• I'm going to respectfully disagree with these criticisms. As I've already said above, I did not make an "improvement" or claim to make one. In fact, I said the opposite in the post. Why did I make the changes? Because the original poster asked for a lodash solution and I thought it would be interesting to compare that solution the original iterative solution to show that it is, in my opinion not obviously better. @Alex L: how can that not be an answer to the question posed? – Justin L. Jan 21 '16 at 5:18
• The question is posed in a way that there isn't a good way to answer it without presenting an alternate solution. I've reinstated this answer with some minor changes to the surrounding text. (Sorry for your harsh welcome to Code Review.) – 200_success Jan 22 '16 at 0:20