Lodash - 在条件下合并两个数组的对象

时间:2017-03-11 17:22:49

标签: javascript arrays collections lodash

我有两个对象数组。

arr1 = [
  {
    myName: 'Adam',
    mySkill: 'CSS',
  },
  {
    myName: 'Mutalib',
    mySkill: 'JavaScript',
  },
];

arr2 = [
  {
    myName: 'Adam',
    myWeight: '112',
  },
  {
    myName: 'Habib',
    myWeight: '221',
  },
];

我想要的结果是一个数组,其中包含具有匹配属性的第一个数组的对象" myName"在第二个数组中,具有相应的第二个数组对象的附加属性。

result = [
  {
    myName = 'Adam'
    mySkill = 'CSS'
    myWeight = '112'
  }
];

5 个答案:

答案 0 :(得分:3)

groups concatenated数组(arr1arr2myName下方的解决方案将使用{{3}删除仅包含一个项目的所有组最后使用rejectmap生成的数组。

var result = _(arr1)
  .concat(arr2)
  .groupBy('myName')
  .reject({ length: 1 })
  .map(_.spread(_.merge))
  .value();



var arr1 = [
  {
    myName: 'Adam',
    mySkill: 'CSS',
  },
  {
    myName: 'Mutalib',
    mySkill: 'JavaScript',
  }
];

var arr2 = [
  {
    myName: 'Adam',
    myWeight: '112',
  },
  {
    myName: 'Habib',
    myWeight: '221',
  }
];

var result = _(arr1)
  .concat(arr2)
  .groupBy('myName')
  .reject({ length: 1 })
  .map(_.spread(_.merge))
  .value();

console.log(result);

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
&#13;
&#13;
&#13;

另一种解决方案是使用merge同时获取两个数组之间的交集和intersectionWith个缺失值。请注意使用assign来促进不变性。

var result = _.intersectionWith(_.cloneDeep(arr1), arr2, function(x, y) {
  return x.myName === y.myName && _.assign(x, y);
});

&#13;
&#13;
var arr1 = [
  {
    myName: 'Adam',
    mySkill: 'CSS',
  },
  {
    myName: 'Mutalib',
    mySkill: 'JavaScript',
  }
];

var arr2 = [
  {
    myName: 'Adam',
    myWeight: '112',
  },
  {
    myName: 'Habib',
    myWeight: '221',
  }
];

var result = _.intersectionWith(_.cloneDeep(arr1), arr2, function(x, y) {
  return x.myName === y.myName && _.assign(x, y);
});
  
console.log(result);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

使用Array.prototype.forEachObject.assign函数的替代原生 JS解决方案:

var arr1 = [
    { myName: 'Adam', mySkill: 'CSS'}, { myName: 'Mutalib', mySkill: 'JavaScript'},
  ],

  arr2 = [
    { myName: 'Adam', myWeight: '112'}, { myName: 'Habib', myWeight: '221'}
  ],
  result = [];
  
arr1.forEach(function (o) {
    arr2.forEach(function (c) {
        if (o.myName === c.myName) result.push(Object.assign({}, o, c));
    })
});

console.log(result);

答案 2 :(得分:1)

只有当myName很常见时,才可以使用哈希表并推送对象。

&#13;
&#13;
var arr1 = [{ myName: 'Adam', mySkill: 'CSS' }, { myName: 'Mutalib', mySkill: 'JavaScript' }],
    arr2 = [{ myName: 'Adam', myWeight: '112' }, { myName: 'Habib', myWeight: '221' }],
    hash = Object.create(null),
    result = [];

arr1.forEach(function (a) {
    hash[a.myName] = { myName: a.myName, mySkill: a.mySkill };
});

arr2.forEach(function (a) {
    if (hash[a.myName]) {
        hash[a.myName].myWeight = a.myWeight;
        result.push(hash[a.myName]);
    }
});

console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 3 :(得分:0)

您还可以借助Map对象执行以下操作。

&#13;
&#13;
function mergeObjectsIfExists(p,a,b){
  var m = a.reduce((m,o) => m.set(o[p],o), new Map());
  return b.reduce((r,o) => m.has(o[p]) ? (r.push(m.set(o[p],Object.assign(m.get(o[p]),o)).get(o[p])),r)
                                       : r, []);
}

var arr1 = [{ myName: 'Adam', mySkill: 'CSS'}, { myName: 'Mutalib', mySkill: 'JavaScript'}, { myName: 'Jessuro', mySkill: 'Haskell'}],
    arr2 = [{ myName: 'Adam', myWeight: '112'}, { myName: 'Habib', myWeight: '221'}, { myName: 'Jessuro', myIQ: '150'}],
  result = mergeObjectsIfExists("myName",arr1,arr2);

console.log(result);
&#13;
&#13;
&#13;

答案 4 :(得分:0)

如果使用lodash/fp,你可以编写功能来达到你想要的效果。假设myName是你的PK(或合并支点),你可以这样做:

const mergeByName = compose(values, spread(merge), map(keyBy('myName')));

> mergeByName([arr1, arr2])
[ { myName: 'Adam', mySkill: 'CSS', myWeight: '112' },
  { myName: 'Mutalib', mySkill: 'JavaScript' },
  { myName: 'Habib', myWeight: '221' } ]