Javascript 如何使用lodash按ID合并两个对象数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38612972/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:38:48  来源:igfitidea点击:

How to merge two arrays of objects by ID using lodash?

javascriptlodash

提问by Shaishab Roy

I have two array with one common field member. how can I merge theme easily?

我有两个数组和一个公共字段成员。如何轻松合并主题?

For example:

例如:

var arr1 = [{
  "member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),
  "bank" : ObjectId("575b052ca6f66a5732749ecc"),
  "country" : ObjectId("575b0523a6f66a5732749ecb")
},
{
  "member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),
  "bank" : ObjectId("575b052ca6f66a5732749ecc"),
  "country" : ObjectId("575b0523a6f66a5732749ecb")
}];

var arr2 = [{
    "member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),
    "name" : 'xxxxxx',
    "age" : 25
},
{
    "member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),
    "name" : 'yyyyyyyyyy',
    "age" : 26
}];

Expected:

预期的:

var merge = [{
  "member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),
  "bank" : ObjectId("575b052ca6f66a5732749ecc"),
  "country" : ObjectId("575b0523a6f66a5732749ecb"),
  "name" : 'xxxxxx',
  "age" : 25
},
{
  "member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),
  "bank" : ObjectId("575b052ca6f66a5732749ecc"),
  "country" : ObjectId("575b0523a6f66a5732749ecb"),
  "name" : 'yyyyyyyyyy',
  "age" : 26
}];

I tried

我试过

var merge = _.unionBy(arr1, arr2, 'member');

but not merged as expected. shown array1value. can any one help me?

但没有按预期合并。显示array1值。谁能帮我?

回答by Mr. Polywhirl

If both arrays are in the correct order; where each item corresponds to its associated member identifier then you can simply use.

如果两个数组的顺序正确;其中每个项目对应于其关联的成员标识符,那么您可以简单地使用。

var merge = _.merge(arr1, arr2);

Which is the short version of:

这是以下的简短版本:

var merge = _.chain(arr1).zip(arr2).map(function(item) {
    return _.merge.apply(null, item);
}).value();

Or, if the data in the arrays is not in any particular order, you can look up the associated item by the member value.

或者,如果数组中的数据没有任何特定顺序,您可以通过成员值查找关联项。

var merge = _.map(arr1, function(item) {
    return _.merge(item, _.find(arr2, { 'member' : item.member }));
});

You can easily convert this to a mixin. See the example below:

您可以轻松地将其转换为 mixin。请参阅下面的示例:

_.mixin({
  'mergeByKey' : function(arr1, arr2, key) {
    var criteria = {};
    criteria[key] = null;
    return _.map(arr1, function(item) {
      criteria[key] = item[key];
      return _.merge(item, _.find(arr2, criteria));
    });
  }
});

var arr1 = [{
  "member": 'ObjectId("57989cbe54cf5d2ce83ff9d6")',
  "bank": 'ObjectId("575b052ca6f66a5732749ecc")',
  "country": 'ObjectId("575b0523a6f66a5732749ecb")'
}, {
  "member": 'ObjectId("57989cbe54cf5d2ce83ff9d8")',
  "bank": 'ObjectId("575b052ca6f66a5732749ecc")',
  "country": 'ObjectId("575b0523a6f66a5732749ecb")'
}];

var arr2 = [{
  "member": 'ObjectId("57989cbe54cf5d2ce83ff9d8")',
  "name": 'yyyyyyyyyy',
  "age": 26
}, {
  "member": 'ObjectId("57989cbe54cf5d2ce83ff9d6")',
  "name": 'xxxxxx',
  "age": 25
}];

var arr3 = _.mergeByKey(arr1, arr2, 'member');

document.body.innerHTML = JSON.stringify(arr3, null, 4);
body { font-family: monospace; white-space: pre; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"></script>

回答by Ori Drori

Create dictionaries for both arrays using _.keyBy(), mergethe dictionaries, and convert the result to an array with _.values(). In this way, the order of the arrays doesn't matter. In addition, it can also handle arrays of different length.

使用 为两个数组创建字典_.keyBy()合并字典,并使用 将结果转换为数组_.values()。这样,数组的顺序无关紧要。此外,它还可以处理不同长度的数组。

const ObjectId = (id) => id; // mock of ObjectId
const arr1 = [{"member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),"bank" : ObjectId("575b052ca6f66a5732749ecc"),"country" : ObjectId("575b0523a6f66a5732749ecb")},{"member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),"bank" : ObjectId("575b052ca6f66a5732749ecc"),"country" : ObjectId("575b0523a6f66a5732749ecb")}];
const arr2 = [{"member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),"name" : 'xxxxxx',"age" : 25},{"member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),"name" : 'yyyyyyyyyy',"age" : 26}];

const merged = _(arr1) // start sequence
  .keyBy('member') // create a dictionary of the 1st array
  .merge(_.keyBy(arr2, 'member')) // create a dictionary of the 2nd array, and merge it to the 1st
  .values() // turn the combined dictionary to array
  .value(); // get the value (array) out of the sequence

console.log(merged);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"></script>

Using ES6 Map

使用 ES6地图

Concat the arrays, and reducethe combined array to a Map. Use Object#assignto combine objects with the same memberto a new object, and store in map. Convert the map to an array with Map#valuesand spread:

连接数组,并将组合数组缩减为 Map。使用Object#assign将具有相同对象的对象组合member为一个新对象,并存储在 map 中。使用Map#valuesspread将地图转换为数组:

const ObjectId = (id) => id; // mock of ObjectId
const arr1 = [{"member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),"bank" : ObjectId("575b052ca6f66a5732749ecc"),"country" : ObjectId("575b0523a6f66a5732749ecb")},{"member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),"bank" : ObjectId("575b052ca6f66a5732749ecc"),"country" : ObjectId("575b0523a6f66a5732749ecb")}];
const arr2 = [{"member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),"name" : 'xxxxxx',"age" : 25},{"member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),"name" : 'yyyyyyyyyy',"age" : 26}];

const merged = [...arr1.concat(arr2).reduce((m, o) => 
  m.set(o.member, Object.assign(m.get(o.member) || {}, o))
, new Map()).values()];

console.log(merged);