Lodash合并阵列并处理重复



我有两个数组:

var a = [
    {aId: 1, name: "a1"}, 
    {aId: 2, name: "a2"}
];
var b = [
    {parentId: 1, description: "b1"}, 
    {parentId: 1, description: "b2"}, 
    {parentId: 2, description: "b3"}
];

我想基于parentid === aid;

合并这些阵列

我做到了:

var c = _.map(a, function(obj) {
    return _.assign(obj, _.find(b, {parentId: obj.aId}));
})

jsfiddle

这可以按预期工作,但是我需要它处理重复项 - 当找到匹配项时,它会正确合并,但是我需要将其推入新属性,而不是合并。

我得到的:

[ 
    {aId: 1, name: "a1", description: "b1"}, 
    {aId: 2, name: "a2", description: "b3"}
]

我想要的:

[ 
    {
        aId: 1, 
        name: "a1", 
        b: [
            {parentId: 1, description: "b1"}, 
            {parentId: 1, description: "b2"}
        ]
     }, 
     {
        aId: 2, 
        name: "a2", 
        b: [
            {parentId: 2, description: "b1"}
        ]
     }
]

当然可以省略公共属性;

编辑

虽然此答案非常有帮助,并且在一定程度上满足了原始问题,但有关评论中突变的讨论可能会导致意外行为,例如使用Redux或其他依赖不可变状态的库。p>原始答案使用导致突变的_.assign。下面使用ES6扩展操作员将新对象返回新数组。

const a = [{aId: 1, name: "a1"}, {aId: 2, name: "a2"}];
const b = [{parentId: 1, description: "b1"}, {parentId: 1, description: "b2"}, {parentId: 2, description: "b3"}];
const c = _.map(a, (obj) => 
  ({ ...obj, ...{ b: _.filter(b, {parentId: obj.aId}) }});
console.log('mimick original', c);

原始答案:

您的代码几乎完成了;在_.Assign()中,您可以通过属性b传递一个对象,等于_.filter()的结果,而不是_.find():

{
  b: _.filter(b, {parentId: obj.aId})
}

请注意,_.find()返回匹配的元素,else undefined and _.filter()返回新的过滤阵列。

代码:

var a = [{aId: 1, name: "a1"}, {aId: 2, name: "a2"}],
    b = [{parentId: 1, description: "b1"}, {parentId: 1, description: "b2"}, {parentId: 2, description: "b3"}];
_.map(a, function(obj) {
  return _.assign(obj, {
    b: _.filter(b, {parentId: obj.aId})
  });
});
console.log(a);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

最新更新