1

I'm using node.js and lodash.

I have data like this:

[ 
  { 
    to: [ '[email protected]', '[email protected]' ],
    submittedSubs: [ [Object] ] 
  },
  { 
    to: [ '[email protected]', '[email protected]' ],
    submittedSubs: [ [Object], [Object], [Object] ] 
  } 
]

I'd like to turn it into data like this where it's "sorted" by to

[ 
  { 
    to: '[email protected]', 
    submittedSubs: [ [Object],[Object], [Object], [Object] ] 
  },
  { 
    to: '[email protected]', 
    submittedSubs: [ [Object] ] 
  },
  { 
    to: '[email protected]',
    submittedSubs: [ [Object], [Object], [Object] ] 
  }
]

How can I do this?

I've tried this:

spam[0].to.push('[email protected]');  
spam[0].to.push('[email protected]'); 
spam[1].to.push('[email protected]');  
spam[1].to.push('[email protected]'); 

console.log('data is',spam);

var byUser=[];
_.each(spam, function(data){
    _.each(data.to,function(addr){
        byUser.push({to:addr,submittedSubs:data.submittedSubs});
    });
});
console.log('attempt',_.merge(byUser));

But that gives me this:

[ { to: '[email protected]', submittedSubs: [ [Object] ] },
{ to: '[email protected]', submittedSubs: [ [Object] ] },
{ to: '[email protected]', submittedSubs: [ [Object], [Object], [Object] ] },
{ to: '[email protected]', submittedSubs: [ [Object], [Object], [Object] ] } ]
1
  • seems like the easiest way would be to start by creating an object with the email address as the key, and the value being an array of objects. you can then convert that back into an array and sort it on to field. Commented Jul 21, 2015 at 21:35

2 Answers 2

1

This'll work for you:

var unique = {};
byUser.forEach(function(user) {
    unique[user.to] = unique[user.to] || [];
    unique[user.to] = unique[user.to].concat(user.submittedSubs);
});
unique = Object.keys(unique).map(function (key, i) {
    return {to: key, submittedSubs: unique[key]};
});

/*
[ { to: '[email protected]', submittedSubs: [ [Object] ] },
{ to: '[email protected]', submittedSubs: [ [Object] ] },
{ to: '[email protected]', submittedSubs: [ [Object], [Object], [Object], [Object] ] } ]
*/

I stand by that this should be achievable using the callback feature of _.uniq but I couldn't get it to work the way you needed it to.

You should be able to use _.uniq from on your final array:

_.uniq(byUser, "to");

/*
[ { to: '[email protected]', submittedSubs: [ [Object] ] },
{ to: '[email protected]', submittedSubs: [ [Object] ] },
{ to: '[email protected]', submittedSubs: [ [Object], [Object], [Object] ] } ]
*/
Sign up to request clarification or add additional context in comments.

1 Comment

I'd like foo@bar to contain four submittedSubs, though. One from the first object, and three from the second object. but with this, it only contains one.
1

I imagine there's some nice lodash facilities to shorten this up a bit, but here's a vanilla-js solution:

var data = [ 
  { 
    to: [ '[email protected]', '[email protected]' ],
    submittedSubs: [{ id: 'sub1' }] 
  },
  { 
    to: [ '[email protected]', '[email protected]' ],
      submittedSubs: [{ id: 'sub2' }, { id: 'sub3' }, { id: 'sub4' }]
  } 
];

var emailSubsMap = data.reduce(function(result, record) {
    record.to.forEach(function(email) {
        result[email] = (result[email] || [])
            .concat(record.submittedSubs);
    });
    return result;
}, {});

var formatted = Object.keys(emailSubsMap).map(function(email) {
    return { to: email, submittedSubs: emailSubsMap[email] };
}).sort(function(a, b) {
    return a.to <= b.to ? -1 : 1;
});

console.log(JSON.stringify(formatted));

(Formatted) console output:

[
    {
        "to": "[email protected]",
        "submittedSubs": [
            { "id": "sub1" }
        ]
    },
    {
        "to": "[email protected]",
        "submittedSubs": [
            { "id": "sub2" },
            { "id": "sub3" },
            { "id": "sub4" }
        ]
    },
    {
        "to": "[email protected]",
        "submittedSubs": [
            { "id": "sub1" },
            { "id": "sub2" },
            { "id": "sub3" },
            { "id": "sub4" }
        ]
    }
]

Note that I mocked up what the submittedSubs objects might look like, simply for testing purposes.

JSFiddle Example

A couple notes about the sorting:

3 Comments

When I run this I get [TypeError: Object [email protected] has no method 'forEach']
Are you sure you copied it correctly? Please refer to the jsfiddle example to see it functioning correctly: jsfiddle.net/vgexn06L/1
Alternatively, is it possible that not all of your data is shaped like in the example? E.g., perhaps some of the to values are single values instead of arrays?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.