Javascript 合并 2 个对象数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7146217/
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-24 01:02:39  来源:igfitidea点击:

Merge 2 arrays of objects

javascriptjqueryarrays

提问by Alexander

Lets have a look at an example.

让我们看一个例子。

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});

I need to merge those 2 arrays of objects and create the following array:

我需要合并这 2 个对象数组并创建以下数组:

arr3 = new Array({name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'});

Is there any JavaScript or jQuery function to do this?

是否有任何 JavaScript 或 jQuery 函数可以做到这一点?

$.extenddoesn't suit me. It returns

$.extend不适合我。它返回

arr4 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});

回答by Jahanzaib Aslam

If you want to merge 2 arrays of objects in JavaScript. You can use this one line trick

如果你想在 JavaScript 中合并 2 个对象数组。你可以使用这个单行技巧

Array.prototype.push.apply(arr1,arr2);

Array.prototype.push.apply(arr1,arr2);

For Example

例如

var arr1 = [{name: "lang", value: "English"},{name: "age", value: "18"}];
var arr2 = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];

Array.prototype.push.apply(arr1,arr2); 

console.log(arr1);  // final merged result will be in arr1

Output:

输出:

[{"name":"lang","value":"English"},
{"name":"age","value":"18"},
{"name":"childs","value":"5"},
{"name":"lang","value":"German"}]

回答by Nguy?n Bá Vinh

With ES6 you can do it very easy as below:

使用 ES6,你可以很容易地做到这一点,如下所示:

var arr1 = new Array({name: "lang", value: "German"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
var arr3 = [...arr1, ...arr2];

Output:

输出:

    arr3 = [
      {"name":"lang","value":"German"},
      {"name":"age","value":"18"},
      {"name":"childs","value":"5"},
      {"name":"lang","value":"German"}
    ]

回答by bob

For those who are experimenting with modern things:

对于那些正在尝试现代事物的人:

var odd = [
    { name : "1", arr: "in odd" },
    { name : "3", arr: "in odd" }
];

var even = [
    { name : "1", arr: "in even" },
    { name : "2", arr: "in even" },
    { name : "4", arr: "in even" }
];

// ----
// ES5 using Array.filter and Array.find
function merge(a, b, prop){
  var reduced = a.filter(function(aitem){
      return ! b.find(function(bitem){
          return aitem[prop] === bitem[prop];
      });
  });
  return reduced.concat(b);
}
console.log( "ES5", merge(odd, even, "name") );

// ----
// ES6 arrow functions
function merge(a, b, prop){
    var reduced =  a.filter( aitem => ! b.find ( bitem => aitem[prop] === bitem[prop]) )
  return reduced.concat(b);
}
console.log( "ES6", merge(odd, even, "name") );

// ----
// ES6 one-liner
var merge = (a, b, p) => a.filter( aa => ! b.find ( bb => aa[p] === bb[p]) ).concat(b);


console.log( "ES6 one-liner", merge(odd, even, "name") );

// Results
// ( stuff in the "b" array replaces things in the "a" array )
// [
//    {
//         "name": "3",
//         "arr": "in odd"
//     },
//     {
//         "name": "1",
//         "arr": "in even"
//     },
//     {
//         "name": "2",
//         "arr": "in even"
//     },
//     {
//         "name": "4",
//         "arr": "in even"
//     }
// ]

回答by guya

Update 12 Oct 2019

2019 年 10 月 12 日更新

New version based only on newer Javascript and without the need of any 3rd party library.

新版本仅基于较新的 Javascript,不需要任何 3rd 方库。

const mergeByProperty = (target, source, prop) => {
  source.forEach(sourceElement => {
    let targetElement = target.find(targetElement => {
      return sourceElement[prop] === targetElement[prop];
    })
    targetElement ? Object.assign(targetElement, sourceElement) : target.push(sourceElement);
  })
}
var target /* arr1 */ = [{name: "lang", value: "English"}, {name: "age", value: "18"}];
var source /* arr2 */ = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];

mergeByProperty(target, source, 'name');

console.log(target)

This answer was getting old, libs like lodash and underscore are much less needed these days. In this new version, the target (arr1)array is the one we're working with and want to keep up to date. The source (arr2)array is where the new data is coming from, and we want it merged into our targetarray.

这个答案已经过时了,现在不太需要像 lodash 和 underscore 这样的库。在这个新版本中,目标 (arr1)数组是我们正在使用并希望保持最新的数组。该源(ARR2)阵列是在新的数据是从哪里来的,我们希望它融入我们的目标阵列。

We loop over the sourcearray looking for new data, and for every object that is not yet found in our targetarray we simply add that object using target.push(sourceElement)If, based on our key property ('name'), an object is already in our target array - we update its properties and values using Object.assign(targetElement, sourceElement). Our “target” will always be the same array and with updated content.

我们遍历数组以寻找新数据,对于尚未在目标数组中找到的每个对象,我们只需使用target.push(sourceElement)添加该对象, 如果基于我们的关键属性 ('name'), object 已经在我们的目标数组中 - 我们使用Object.assign(targetElement, sourceElement)更新它的属性和值。我们的“目标”将始终是相同的数组和更新的内容。



Old answer using underscore or lodash

使用下划线或 lodash 的旧答案

I always arrive here from google and I'm always not satisfy from the answers. YOU answer is good but it'll be easier and neater using underscore.js

我总是从谷歌来到这里,我总是对答案不满意。你的回答很好,但使用 underscore.js 会更容易、更整洁

DEMO: http://jsfiddle.net/guya/eAWKR/

演示:http: //jsfiddle.net/guya/eAWKR/

Here is a more general function that will merge 2 arrays using a property of their objects. In this case the property is 'name'

这是一个更通用的函数,它将使用对象的属性合并 2 个数组。在这种情况下,属性是“名称”

var arr1 = [{name: "lang", value: "English"}, {name: "age", value: "18"}];
var arr2 = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];

function mergeByProperty(arr1, arr2, prop) {
  _.each(arr2, function(arr2obj) {
    var arr1obj = _.find(arr1, function(arr1obj) {
      return arr1obj[prop] === arr2obj[prop];
    });

    arr1obj ? _.extend(arr1obj, arr2obj) : arr1.push(arr2obj);
  });
}

mergeByProperty(arr1, arr2, 'name');

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

[{name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'}]

回答by YOU

var arr3 = [];
for(var i in arr1){
   var shared = false;
   for (var j in arr2)
       if (arr2[j].name == arr1[i].name) {
           shared = true;
           break;
       }
   if(!shared) arr3.push(arr1[i])
}
arr3 = arr3.concat(arr2);

enter image description here

在此处输入图片说明

回答by Andrew D.

Merging two arrays:

合并两个数组:

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
var result=arr1.concat(arr2);
// result: [{name: "lang", value: "English"}, {name: "age", value: "18"}, {name : "childs", value: '5'}, {name: "lang", value: "German"}]

Merging two arrays without duplicated values for 'name':

合并两个没有重复值的 'name' 数组:

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
var i,p,obj={},result=[];
for(i=0;i<arr1.length;i++)obj[arr1[i].name]=arr1[i].value;
for(i=0;i<arr2.length;i++)obj[arr2[i].name]=arr2[i].value;
for(p in obj)if(obj.hasOwnProperty(p))result.push({name:p,value:obj[p]});
// result: [{name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'}]

回答by bh4r4th

Very simple using ES6 spread operator:

使用 ES6 扩展运算符非常简单:

const array1 = [{a: 'HI!'}, {b: 'HOW'}]
const array2 = [{c: 'ARE'}, {d: 'YOU?'}]

const mergedArray = [ ...array1, ...array2 ]
console.log('Merged Array: ', mergedArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Merged Array: [ {a: 'HI!'}, {b: 'HOW'} {c: 'ARE'}, {d: 'YOU?'} ]

Merged Array: [ {a: 'HI!'}, {b: 'HOW'} {c: 'ARE'}, {d: 'YOU?'} ]

Note:The above solution is to just merge two arrays using ES6 spread operator.

注意:上面的解决方案是使用 ES6 扩展运算符合并两个数组。

Edit on 07 January 2020 by @bh4r4th :As the context changed due to edits after my initial solution. I would like to update my solution to match current criteria. i.e.,

2020 年 1 月 7 日由 @bh4r4th 编辑:由于在我的初始解决方案之后进行了编辑,上下文发生了变化。我想更新我的解决方案以匹配当前标准。IE,

  1. Merger array objects without creating duplicate objects and,

  2. update the valueif the nameproperty already exists in the prior array

  1. 合并数组对象而不创建重复对象,

  2. value如果name属性已存在于先前数组中,则更新

const arr1 = [
    { name: "lang", value: "English" },
    { name: "age", value: "18" }
]
const arr2 = [
    { name: "childs", value: '2' }, 
    { name: "lang", value: "German" }
]
const arr3 = [
    { name: "lang", value: "German" },
    { name: "age", value: "28" },
    { name: "childs", value: '5' }
]

// Convert to key value dictionary or object
const convertToKeyValueDict = arrayObj => {
    const val = {}
    arrayObj.forEach(ob => {
        val[ob.name] = ob.value
    })
    return val
}

// update or merge array
const updateOrMerge = (a1, a2) => {
    const ob1 = convertToKeyValueDict(a1)
    const ob2 = convertToKeyValueDict(a2)
    // Note: Spread operator with objects used here
    const merged_obj = {...ob1, ...ob2}
    const val = Object.entries(merged_obj)
    return val.map(obj => ({ name: obj[0], value: obj[1] }))
}

const v1 = updateOrMerge(arr1, arr2)
const v2 = updateOrMerge(v1, arr3)
console.log(`Merged array1 and array2: ${JSON.stringify(v1)} \n\n`)
console.log(`Merged above response and array3: ${JSON.stringify(v2)} \n\n`)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

回答by knikolov

The easiest way is with some ES6 magic:

最简单的方法是使用一些 ES6 魔法:

Merge two with duplicates:

合并两个重复项:

const a = [{a: 1}, {b: 2}]
const b = [{a: 1}]

const result = a.concat(b) // [{a: 1}, {b: 2}, {a: 1}]

Without duplicates it is same as the above plus:

没有重复,它与上述加号相同:

const distinct = [...new Set(result.map(item => item.YOUR_PROP_HERE))]

const distinct = [...new Set(result.map(item => item.YOUR_PROP_HERE))]

回答by marktuk

This is how I've tackled a similar issue in an ES6 context:

这是我在 ES6 上下文中解决类似问题的方式:

function merge(array1, array2, prop) {
    return array2.map(function (item2) {
        var item1 = array1.find(function (item1) {
            return item1[prop] === item2[prop];
        });
        return Object.assign({}, item1, item2);
    });
}

Note: This approach will not return any items from array1 that don't appear in array2.

注意:此方法不会从 array1 返回任何未出现在 array2 中的项目。



EDIT:I have some scenarios where I want to preserve items that don't appear in the second array so I came up with another method.

编辑:我有一些场景,我想保留没有出现在第二个数组中的项目,所以我想出了另一种方法。

function mergeArrays(arrays, prop) {
    const merged = {};

    arrays.forEach(arr => {
        arr.forEach(item => {
            merged[item[prop]] = Object.assign({}, merged[item[prop]], item);
        });
    });

    return Object.values(merged);
}

var arr1 = [
    { name: 'Bob', age: 11 },
    { name: 'Ben', age: 12 },
    { name: 'Bill', age: 13 },
];

var arr2 = [
    { name: 'Bob', age: 22 },
    { name: 'Fred', age: 24 },
    { name: 'Hyman', age: 25 },
    { name: 'Ben' },
];

console.log(mergeArrays([arr1, arr2], 'name'));

回答by Pietro

With lodash:

使用 lodash:

_.uniqBy([...arr1, ...arr2], 'name')