Node.js 使用lodash中的键值合并对象数组?

Node.js 使用lodash中的键值合并对象数组?,node.js,lodash,Node.js,Lodash,我正在使用node.js和lodash 我有这样的数据: [ { to: [ 'foo@bar.com', 'foo1@bar.com' ], submittedSubs: [ [Object] ] }, { to: [ 'foo@bar.com', 'foo2@bar.com' ], submittedSubs: [ [Object], [Object], [Object] ] } ] 我想把它变成这样的数据,按排序到 [ {

我正在使用node.js和lodash

我有这样的数据:

[ 
  { 
    to: [ 'foo@bar.com', 'foo1@bar.com' ],
    submittedSubs: [ [Object] ] 
  },
  { 
    to: [ 'foo@bar.com', 'foo2@bar.com' ],
    submittedSubs: [ [Object], [Object], [Object] ] 
  } 
]
我想把它变成这样的数据,按
排序到

[ 
  { 
    to: 'foo@bar.com', 
    submittedSubs: [ [Object],[Object], [Object], [Object] ] 
  },
  { 
    to: 'foo1@bar.com', 
    submittedSubs: [ [Object] ] 
  },
  { 
    to: 'foo2@bar.com',
    submittedSubs: [ [Object], [Object], [Object] ] 
  }
]
我该怎么做

我试过这个:

spam[0].to.push('foo@bar.com');  
spam[0].to.push('foo1@bar.com'); 
spam[1].to.push('foo@bar.com');  
spam[1].to.push('foo2@bar.com'); 

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));
但这给了我:

[ { to: 'foo@bar.com', submittedSubs: [ [Object] ] },
{ to: 'foo1@bar.com', submittedSubs: [ [Object] ] },
{ to: 'foo@bar.com', submittedSubs: [ [Object], [Object], [Object] ] },
{ to: 'foo2@bar.com', submittedSubs: [ [Object], [Object], [Object] ] } ]
这将对您有用:

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: 'foo@bar.com', submittedSubs: [ [Object] ] },
{ to: 'foo1@bar.com', submittedSubs: [ [Object] ] },
{ to: 'foo2@bar.com', submittedSubs: [ [Object], [Object], [Object], [Object] ] } ]
*/

我坚持认为,使用
\uq.uniq
的回调功能应该可以实现这一点,但我无法让它以您需要的方式工作

您应该能够从最终阵列上使用:

_.uniq(byUser, "to");

/*
[ { to: 'foo@bar.com', submittedSubs: [ [Object] ] },
{ to: 'foo1@bar.com', submittedSubs: [ [Object] ] },
{ to: 'foo2@bar.com', submittedSubs: [ [Object], [Object], [Object] ] } ]
*/

我想有一些很好的
lodash
工具可以将这一点缩短一点,但这里有一个普通的js解决方案:

var data = [ 
  { 
    to: [ 'foo@bar.com', 'foo1@bar.com' ],
    submittedSubs: [{ id: 'sub1' }] 
  },
  { 
    to: [ 'foo@bar.com', 'foo2@bar.com' ],
      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));
注意,我模拟了
submittedSubs
对象的外观,只是为了测试

关于排序的几个注意事项:

  • 我的第一个版本排序不正确。。。它已更新。:)
  • 您请求的排序方法不遵循JavaScript的“本机”字符串排序顺序。例如,
    ['foo@bar.com', 'foo2@bar.com', 'foo1@bar.com'].sort()-->['foo1@bar.com','foo2@bar.com','foo@bar.com“]
    ,所以如果您真的想要
    foo@bar.com
    foo1@bar.com
    ,您需要更详细地定义排序标准

最简单的方法似乎是首先创建一个以电子邮件地址为键的对象,其值是一个对象数组。然后,您可以将其转换回数组,并在
to
字段中对其进行排序foo@bar
包含四个
提交的submittedsub
。一个来自第一个对象,三个来自第二个对象。但有了这个,它只包含一个foo@bar.com没有方法“forEach”]
您确定复制的方法正确吗?请参考JSFIDLE示例以查看它是否正常工作:或者,您的所有数据是否都可能不是示例中的形状?例如,
的一些值可能是单个值而不是数组?
[
    {
        "to": "foo1@bar.com",
        "submittedSubs": [
            { "id": "sub1" }
        ]
    },
    {
        "to": "foo2@bar.com",
        "submittedSubs": [
            { "id": "sub2" },
            { "id": "sub3" },
            { "id": "sub4" }
        ]
    },
    {
        "to": "foo@bar.com",
        "submittedSubs": [
            { "id": "sub1" },
            { "id": "sub2" },
            { "id": "sub3" },
            { "id": "sub4" }
        ]
    }
]