合并 2 个对象数组

IT技术 javascript jquery arrays
2021-01-11 01:43:59

让我们看一个例子。

var arr1 = new Array({name: "lang", value: "English"},
                     {name: "age", value: "18"});

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

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

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

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

$.extend不适合我。它返回

var arr4 = new Array({name : "childs", value: '5'},
                     {name: "lang", value: "German"});
6个回答

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

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

例如

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

输出:

[{"name":"lang","value":"English"},
{"name":"age","value":"18"},
{"name":"childs","value":"5"},
{"name":"lang","value":"German"}]
结果是不一样的。concat将返回一个新数组并破坏您拥有的任何引用。
2021-03-12 01:43:59
不适用于更新值。证明:jsfiddle.net/aminajani17/s76x6hh4
2021-03-21 01:43:59
与更简单的结果相同: arr1 = arr1.concat(arr2)
2021-03-24 01:43:59
这不能回答问题,结果数组应该有 3 个对象,而不是 4 个。您更改了示例值。基本上 OP 想要的是合并两个对象数组并删除重复值。
2021-04-04 01:43:59
但这不是合并!
2021-04-05 01:43:59

使用 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];

输出:

    arr3 = [
      {"name":"lang","value":"German"},
      {"name":"age","value":"18"},
      {"name":"childs","value":"5"},
      {"name":"lang","value":"German"}
    ]
这不符合 OP 的要求,不应该有第二个对象包含 { name: 'lang', value: 'German'}
2021-03-12 01:43:59
我不知道为什么这个答案被投票。@daveanderson88 想要的是不同的这个答案。
2021-03-22 01:43:59
而不是new Array( ... )仅仅编写更容易[ ... ]
2021-03-24 01:43:59

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

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"
//     }
// ]


// for posterity, here's the old skool version

function merge(a, b, prop) {
  var reduced = [];
  for (var i = 0; i < a.length; i++) {
    var aitem = a[i];
    var found = false;
    for (var ii = 0; ii < b.length; ii++) {
      if (aitem[prop] === b[ii][prop]) {
        found = true;
        break;
      }
    }
    if (!found) {
      reduced.push(aitem);
    }
  }
  return reduced.concat(b);
}

伙计,你是一个救星。谢谢
2021-03-22 01:43:59
也许这应该被称为“mergeOn”?
2021-03-23 01:43:59
我喜欢你的解决方案。ArrA 将覆盖 ArrB 中的对象。不相交的对象将被连接到结果数组const mergeArrayAtoB = (arrA, arrB, property) => arrB.filter(b => !arrA.find(a => b[property] === a[property])).concat(arrA);
2021-03-28 01:43:59

2019 年 10 月 12 日更新

新版本仅基于较新的 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)

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

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


使用下划线或 lodash 的旧答案

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

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

这是一个更通用的函数,它将使用对象的属性合并 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'}]
LOC 中几乎相同,复杂性与@YOU 的答案相同,除了这要慢得多(主要是由于额外的函数调用以及您的答案利用 JS 关联数组技巧来查找具有 O(1) 查找项的项目)。除此之外,您还需要携带一个额外的图书馆。
2021-03-17 01:43:59
@guya 我意识到这是旧的但下划线,lodash 和类似的东西通常已经被使用并有其他好处,而正如你所说的,它们有其他好处,这是一个巨大的假设,说它们通常已经被使用。
2021-03-22 01:43:59
除非您处理极端的边缘情况,否则您不会在性能上有任何差异。关于额外的 lib - 下划线,lodash 等通常已经使用并具有其他好处,无论如何都应该考虑使用它。大多数开发人员和应用程序都将从该解决方案的简单性和通用性中受益。
2021-04-01 01:43:59
新版本适用于 Nodejs。谢谢,愿上帝保佑你!!
2021-04-02 01:43:59

使用 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?'} ]

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

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

  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>

这应该是2019年公认的答案!在查看了投票数更高的其他答案后,我打算提出相同的解决方案!@Alexander 很容易错过,但请接受这个!
2021-03-20 01:43:59
不正确。提问者特别希望 REPLACE 对象具有重复的属性,而不是简单地附加它们。
2021-03-23 01:43:59
我现在更新了解决方案以匹配问题的更改上下文。
2021-03-28 01:43:59
感谢您指出 @HaveSpacesuit 。我在 2018 年回答了这个问题,当时上下文只是合并两个数组。将很快编辑此答案以set在合并时使用以删除重复项。这将创建新的变量参数,但代码最少。但是,我不是有效负载的忠实粉丝,有效负载的名称定义为不同类型的属性和值。相反,我更喜欢[ { lang: &#39;German&#39;, age: 25}] . 这样,在服务之间进行通信时,有效载荷重量将最小化。
2021-03-31 01:43:59