【问题标题】:Merge 2 arrays of objects合并 2 个对象数组
【发布时间】:2011-11-01 01:15:15
【问题描述】:

让我们看一个例子。

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 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"});

【问题讨论】:

  • {name: "lang", value: "English"} 发生了什么事?
  • 对不起。我提到 $.extend,而不是 $.merge。
  • 我的意思是,其中的逻辑是什么?你想如何合并数组?从您的示例中不清楚。
  • @ShadowWizard,我认为 OP 的意思是如果存在则更新,如果不存在则推送。
  • 注意:这个问题在 2018 年发生了根本性的变化,当时它被编辑为两个“lang”条目都说“德语”。原来,一个说“English”,另一个说“German”。这将问题的含义从“每个'名称'只保留一个元素”更改为“保留元素,除非所有属性都是重复的”。我正在恢复该编辑,因为鉴于该编辑,某些答案将不再有意义。这是一个为什么应该避免对问题进行重大修改的示例。只需进行语法和样式更改,不会改变含义。该意见应该是comment,而不是edit

标签: javascript jquery arrays


【解决方案1】:

如果你想在 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"}]

【讨论】:

  • 不能用于更新值。证明在这里:jsfiddle.net/aminajani17/s76x6hh4
  • 与更简单的结果相同:arr1 = arr1.concat(arr2)
  • 但这不是合并!
  • 结果不一样。 concat 将返回一个新数组并破坏您拥有的所有引用。
  • 这没有回答问题,结果数组应该有 3 个对象,而不是 4 个。您更改了示例值。基本上OP想要的是合并两个对象数组并删除重复值。
【解决方案2】:

使用 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'}
  • 我不知道为什么这个答案被投票。 @daveanderson88 想要的是不同的答案。
  • [ ... ],而不是new Array( ... )
【解决方案3】:

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

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);
}

【讨论】:

  • 也许这应该叫做“mergeOn”?
  • 我喜欢你的解决方案。 ArrA 将覆盖 ArrB 中的对象。不相交的对象将被连接到结果数组const mergeArrayAtoB = (arrA, arrB, property) =&gt; arrB.filter(b =&gt; !arrA.find(a =&gt; b[property] === a[property])).concat(arrA);
  • 伙计,你是救生员。谢谢
【解决方案4】:

2019 年 10 月 12 日更新

新版本仅基于较新的 Javascript,无需任何第三方库。

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 这样的库了。 在这个新版本中,target (arr1) 数组是我们正在使用并希望保持最新的数组。 source (arr2) 数组是新数据的来源,我们希望将其合并到我们的 target 数组中。

我们循环遍历 source 数组以查找新数据,对于尚未在 target 数组中找到的每个对象,我们只需使用 添加该对象target.push(sourceElement) 如果根据我们的 key 属性 ('name'),一个对象已经在我们的目标数组中 - 我们使用 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);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.core.min.js"&gt;&lt;/script&gt;
[{name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'}]

【讨论】:

  • 在 LOC 中几乎相同,复杂性与@YOU 的答案不同,只是速度要慢得多(主要是由于额外的函数调用以及您的答案利用 JS 关联数组技巧来查找具有 O( 1)查找)。除此之外,您还需要携带一个额外的库。
  • 除非您处理极端情况,否则性能不会有任何差异。关于额外的库 - 下划线、lodash 等通常已经使用并且还有其他好处,无论如何都应该考虑使用它。大多数开发人员和应用程序都将从该解决方案的简单性和通用性中受益。
  • @guya 我知道这已经过时了,但是 underscore、lodash 等通常已经被使用并且还有其他好处 而正如您所说它们还有其他好处,这是一个巨大的假设说它们通常已经被使用了。
  • 新版本在 Nodejs 中工作。谢谢,愿上帝保佑你!!
【解决方案5】:

使用 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 扩展运算符合并两个数组。

@bh4r4th 于 2020 年 1 月 7 日编辑: 由于在我最初的解决方案之后由于编辑而改变了上下文。我想更新我的解决方案以符合当前标准。即,

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

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

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 很容易错过,但请接受这个!
  • 不正确。如果对象具有重复的属性,提问者特别想替换它们,而不是简单地附加它们。
  • 感谢您指出 @HaveSpacesuit 。当上下文只是合并两个数组时,我在 2018 年回答了这个问题。将很快编辑此答案以在合并时使用set 删除重复项。这将创建新的变量参数,但代码最少。但是,我不是有效载荷的忠实拥护者,它的名称定义为属性,值定义为不同的类型。相反,我更喜欢[ { lang: &amp;#39;German&amp;#39;, age: 25}] 。这样,在服务之间进行通信时,有效负载的重量将最小化。
  • 我现在已经更新了解决方案以匹配问题的更改上下文。
【解决方案6】:
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);

【讨论】:

  • 这个答案的时间复杂度很差 (O(n^2))。使用哈希映射可以实现 O(n) 解决方案。
【解决方案7】:

合并两个数组:

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

合并两个没有重复值的数组'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'}]

【讨论】:

  • Array.concat 是将 2 个数组合并为一个的正确方法。我也喜欢扩展的假设,即解决了“真正”合并的概念(基于每个数组元素的给定键)。
【解决方案8】:

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

合并两个重复项:

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

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

没有重复就和上面加的一样:

const distinct = [...new Set(result.map(item =&gt; item.YOUR_PROP_HERE))]

【讨论】:

  • concat 不适用于不同性质的项目
【解决方案9】:

我会合并两个具有重复项的数组,然后使用我的this answer 删除重复项。这看起来是最短的方式。

const arr1 = [{
    name: "lang",
    value: "English"
  },
  {
    name: "age",
    value: "18"
  }
];

const arr2 = [{
    name: "childs",
    value: '5'
  },
  {
    name: "lang",
    value: "German"
  }
];

const mergedArray = [...arr1, ...arr2];
const uniqueData = [...mergedArray.reduce((map, obj) => map.set(obj.name, obj), new Map()).values()];

console.log(uniqueData)

【讨论】:

    【解决方案10】:

    使用 lodash:

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

    【讨论】:

    • ES6 语法适用于 2 个数组,而不适用于 2 个对象数组。
    【解决方案11】:

    另一个使用reduce() method的版本:

    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 arr = arr1.concat(arr2).reduce(function(prev, current, index, array){ 
       
       if(!(current.name in prev.keys)) {
          prev.keys[current.name] = index;
          prev.result.push(current);   
       } 
       else{
           prev.result[prev.keys[current.name]] = current;
       }  
    
       return prev;
    },{result: [], keys: {}}).result;
      
    document.getElementById("output").innerHTML = JSON.stringify(arr,null,2);    
    &lt;pre id="output"/&gt;

    【讨论】:

    • 这对我很有用。一个小问题是在合并 3 个大型 json 对象时排序有时很奇怪
    【解决方案12】:

    这就是我在 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);
        });
    }
    

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


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

    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: 'Jack', age: 25 },
        { name: 'Ben' },
    ];
    
    console.log(mergeArrays([arr1, arr2], 'name'));
    

    【讨论】:

      【解决方案13】:

      jsut 使用 vanilla js(ES6 版本)

      // no need new Array constructor, just using an array literal
      const arr1 = [{name: "lang", value: "English"}, {name: "age", value: "18"}];
      const arr2 = [{name: "childs", value: '5'}, {name: "lang", value: "German"}];
      
      // 1. create a map
      const map = new Map();
      
      // 2. concat array
      // arr1.concat(arr2) === [...arr1, ...arr2]
      const arr3 = [...arr1, ...arr2];
      
      // 3. for ... of, iterator array
      for(const obj of arr3) {
        if(!map.has(obj.name)) {
          // add
          map.set(obj.name, obj);
        } else {
          // update
          map.set(obj.name, {
            ...map.get(obj.name),
            ...obj,
          });
        }
      }
      
      // 4. get new merged unqiue array
      const arr4 = [...map.values()];
      
      console.log(`result array =`, JSON.stringify(arr4, null, 4));
      
      /*
      
      result array = [
          {
              "name": "lang",
              "value": "German"
          },
          {
              "name": "age",
              "value": "18"
          },
          {
              "name": "childs",
              "value": "5"
          }
      ]
      
      */

      测试 ✅ (Chrome)

      参考

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#array_literals

      【讨论】:

      • 我发现这在我的场景中是最有用的。我有可以共享几个需要连接的关键值的对象。我以相同的方式使用地图,但首先为每个原始数组创建地图。它们的关键是所有项目的组合字符串,这些项目需要相同才能被视为同一个对象。只有在所有内容都相同的情况下,它们才会合并。谢谢
      【解决方案14】:

      简单的解决方案

      var tx = [{"id":1},{"id":2}];
      var tx1 = [{"id":3},{"id":4}];
      
      
      var txHistory = tx.concat(tx1)
      
      console.log(txHistory); 
      // output
       // [{"id":1},{"id":2},{"id":3},{"id":4}];
      

      【讨论】:

        【解决方案15】:

        您可以使用一个对象来收集您的属性,同时替换重复项,然后将该对象展开/展平回一个数组。像这样的:

        function merge(args) {
            args  = Array.prototype.slice.call(arguments);
            var o = { };
            for(var i = 0; i < args.length; ++i)
                for(var j = 0; j < args[i].length; ++j)
                    o[args[i][j].name] = args[i][j].value;
            return o;
        }
        
        function expand(o) {
            var a = [ ];
            for(var p in o)
                if(o.hasOwnProperty(p))
                    a.push({ name: p, value: o[p]});
            return a;
        }
        
        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 arr3 = expand(merge(arr1, arr2));
        

        我不知道这是否是最快的方法,但它适用于任意数量的输入数组;例如,这个:

        var a = expand(
            merge(
                [{name: "lang", value: "English"}, {name: "age", value: "18"}],
                [{name: "childs", value: '5'}, {name: "lang", value: "German"}],
                [{name: 'lang', value: 'Pancakes'}]
            )
        );
        

        a 中为您提供与在arr3 中相同的内容,其中“German”替换为“Pancakes”。

        当然,这种方法确实假设您的对象都具有相同的{name: ..., value: ...} 形式。

        你可以看到它在这里工作(请打开你的控制台):http://jsfiddle.net/ambiguous/UtBbB/

        【讨论】:

          【解决方案16】:

          您可以使用以下功能

          const merge = (a, b, key = "id") =>
            a.filter(elem => !b.find(subElem => subElem[key] === elem[key]))
             .concat(b);
          

          试试

          merge(arr1, arr2, 'name');
          

          【讨论】:

          • 感谢 Diago 方法与 ES6 不可变特性 ``` export const mergeArrays = (a1, a2, key="id") => a1 && a2 != null ? [...a1.filter(a => !a2.find(p => p[key] === a[key])), ...a2] : null; ```
          【解决方案17】:

          利用 JS Map 的解决方案:

          const merge = (arr1, arr2, prop) => {
              const resultMap = new Map(arr1.map((item) => [item[prop], item]));
              arr2.forEach((item) => {
                  const mapItem = resultMap.get(item[prop]);
                  if (mapItem) Object.assign(mapItem, item);
                  else resultMap.set(item[prop], item);
              });
              return [...resultMap.values()];
          };
          
          const arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
          const arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
          
          console.log(merge(arr1, arr2, "name"));
          

          产生:

          【讨论】:

          • 这应该是公认的答案!太棒了! @Alexandar 仅供参考
          【解决方案18】:

          jQuery 合并呢?

          http://api.jquery.com/jQuery.merge/

          此处的 jsFiddle 示例:http://jsfiddle.net/ygByD/

          【讨论】:

          • 不会按照指定将英语替换为德语,合并正在沿name 属性进行。
          • 啊,是的,你是对的!我一眼就没有看到那个规范!
          • +1。好吧!另一方面,合并对象的javascript数组是一个很好的功能
          【解决方案19】:

          我遇到了同样的问题,基于guya answer,我扩展了下划线库,还添加了一些我需要的功能。这是Gist

          /**
           * Merges two object-like arrays based on a key property and also merges its array-like attributes specified in objectPropertiesToMerge.
           * It also removes falsy values after merging object properties.
           *
           * @param firstArray The original object-like array.
           * @param secondArray An object-like array to add to the firstArray.
           * @param keyProperty The object property that will be used to check if objects from different arrays are the same or not.
           * @param objectPropertiesToMerge The list of object properties that you want to merge. It all must be arrays.
           * @returns The updated original array.
           */
          function merge(firstArray, secondArray, keyProperty, objectPropertiesToMerge) {
          
              function mergeObjectProperties(object, otherObject, objectPropertiesToMerge) {
                  _.each(objectPropertiesToMerge, function (eachProperty) {
                      object[eachProperty] = _.chain(object[eachProperty]).union(otherObject[eachProperty]).compact().value();
                  });
              }
          
              if (firstArray.length === 0) {
                  _.each(secondArray, function (each) {
                      firstArray.push(each);
                  });
              } else {
                  _.each(secondArray, function (itemFromSecond) {
                      var itemFromFirst = _.find(firstArray, function (item) {
                          return item[keyProperty] === itemFromSecond[keyProperty];
                      });
          
                      if (itemFromFirst) {
                          mergeObjectProperties(itemFromFirst, itemFromSecond, objectPropertiesToMerge);
                      } else {
                          firstArray.push(itemFromSecond);
                      }
              });
              }
          
              return firstArray;
          }
          
          _.mixin({
                      merge: merge
                  });
          

          希望有用! 问候!

          【讨论】:

            【解决方案20】:

            我最近被这个问题难住了,我来到这里希望得到答案,但接受的答案使用 2 for in 循环,我不喜欢。我终于设法自己做。不依赖于任何库:

            function find(objArr, keyToFind){
                var foundPos = objArr.map(function(ob){
                    return ob.type;
                }).indexOf(keyToFind);
                return foundPos;
            }
            
            function update(arr1,arr2){
                for(var i = 0, len = arr2.length, current; i< len; i++){
                    var pos = find(arr1, arr2[i].name); 
                    current = arr2[i];
                    if(pos !== -1) for(var key in arr2) arr1[pos][key] = arr2[key];
                    else arr1[arr1.length] = current;
                } 
            }
            

            这也保持了arr1的顺序。

            【讨论】:

              【解决方案21】:

              在这里,我首先根据arr2 中是否存在的元素过滤arr1。如果存在,则不要将其添加到结果数组中,否则请添加。然后我将arr2 附加到结果中。

              arr1.filter(item => {
                if (!arr2.some(item1=>item.name==item1.name)) {
                  return item
                }
              }).concat(arr2)
              

              【讨论】:

              • 请为您的答案提供解释。因此,如果任何其他人阅读了问题和答案,则很容易理解。
              • 虽然这个答案可能是正确且有用的,但最好在其中附上一些解释来解释它如何帮助解决问题。如果有更改(可能不相关)导致它停止工作并且用户需要了解它曾经是如何工作的,这在未来变得特别有用。
              • 谢谢你们。我更新了解决方案描述。如果看起来正确,请投票:)
              【解决方案22】:
              let mergeArray = arrA.filter(aItem => !arrB.find(bItem => aItem.name === bItem.name))
              

              【讨论】:

              • 最好为您的代码添加一些解释。
              【解决方案23】:

              发布这个是因为与以前的答案不同,这个答案是通用的,没有外部库 O(n) 实际上过滤掉重复项并保持 OP 要求的顺序(通过放置最后一个匹配元素代替第一次出现):

              function unique(array, keyfunc) {
                  return array.reduce((result, entry) => {
                      const key = keyfunc(entry)
                      if(key in result.seen) {
                          result.array[result.seen[key]] = entry
                      } else {
                          result.seen[key] = result.array.length
                          result.array.push(entry)
                      }
                      return result
                  }, { array: [], seen: {}}).array
              }
              

              用法:

              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 arr3 = unique([...arr1, ...arr2], x => x.name)
              /* arr3 == [ 
                  {name: "lang", value: "German"}, 
                  {name: "age", value: "18"},
                  {name: "childs", value: "5"}
              ]*/
              

              【讨论】:

                【解决方案24】:

                var arr1 = [{ name: "lang", value: "English" }, { name: "age", value: "18" }];
                var arr2 = [{ name: "childs", value: '5' }, { name: "lang", value: "German" }];
                
                function mergeArrayByProperty(arr1, arr2, prop) {
                    var newArray =
                        arr1.map(item => {
                            if (typeof (item[prop]) !== "undefined") {
                                var nItems = arr2.filter(ni => { if (typeof (ni[prop]) !== "undefined" && ni[prop] === item[prop]) return ni; });
                                if (nItems.length > 0) {
                                    item = Object.assign({}, item, nItems[0]);
                                }
                                return item;
                            }
                        });
                    var arr2nd = arr2.flatMap(item => { return item[prop] });
                    var arr1nd = arr1.flatMap(item => { return item[prop] });
                    var nonDupArr = arr2nd.map(p => { if (arr1nd.includes(p) === false) return arr2.filter(i2 => { if (i2[prop] === p) return Object.assign({}, i2) })[0]; });
                    return newArray.concat(nonDupArr).filter(i=>{if(i !== null)return i})
                }
                var arr = mergeArrayByProperty(arr1, arr2, 'name');
                console.log(arr)
                我知道这已经得到了很多回答,但我想我会分享。

                这会在第一个数组中找到重复的键,并合并具有相同键值的第二个数组对象。如果在第二个数组中没有找到值,则使用原始对象。如您所见, lang 在结果集中只找到一次;有德语的价值。

                【讨论】:

                  【解决方案25】:
                  const arr1 = [{ name: "lang", value: "English" }, { name: "age", value: "18" }];
                  const arr2 = [{ name: "childs", value: '5' }, { name: "lang", value: "German" }];
                  
                  const mergeArrOfObjects = (dataset1, dataset2) => {
                      const map1 = new Map();
                      dataset1.map((d1, i) => {
                          map1.set(d1.name, i);
                      })
                      for (let d2 of dataset2) {
                          if (d2 && map1.has(d2.name)) {
                              dataset1[map1.get(d2.name)] = d2;
                          } else if(d2){
                              dataset1.push(d2);
                          }
                      }
                      return dataset1;
                  };
                  
                  const arr3 = mergeArrOfObjects(arr1, arr2);
                  console.log(arr3);
                  

                  【讨论】:

                    【解决方案26】:

                    别想了——试试jquery extend

                    var arr3 = jQuery.extend(arr1,arr2....)
                    

                    【讨论】:

                    • 对不起。正是这个函数返回 arr4。不是 $.merge。最后一个也不适合我,因为它复制了对象。
                    【解决方案27】:

                    var newArray = yourArray.concat(otherArray); console.log('Concatenated newArray: ', newArray);

                    【讨论】:

                    • 我同意这比 Array.protype.push.apply() 答案更有意义,但是,它并没有像 OP 想要的那样进行合并。
                    • 如果你有两个对象的合并数组,你不能使用 'concat' 获得以上输出。请查看jsfiddle.net/jahanzaibaslam/z22n5tuo
                    【解决方案28】:

                    根据@YOU 的回答但保持顺序:

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

                    我知道此解决方案效率较低,但如果您想保持订单并仍更新对象,则必须这样做。

                    【讨论】:

                      【解决方案29】:

                      这是我编写的一个 jQuery 插件,用于通过键合并两个对象数组。请记住,这会就地修改目标数组。

                      (function($) {
                        $.extendObjectArray = function(destArray, srcArray, key) {
                          for (var index = 0; index < srcArray.length; index++) {
                            var srcObject = srcArray[index];
                            var existObject = destArray.filter(function(destObj) {
                              return destObj[key] === srcObject[key];
                            });
                            if (existObject.length > 0) {
                              var existingIndex = destArray.indexOf(existObject[0]);
                              $.extend(true, destArray[existingIndex], srcObject);
                            } else {
                              destArray.push(srcObject);
                            }
                          }
                          return destArray;
                        };
                      })(jQuery);
                      
                      var arr1 = [
                        { name: "lang",   value: "English" },
                        { name: "age",    value: "18"      }
                      ];
                      var arr2 = [
                        { name: "childs", value: '5'       },
                        { name: "lang",   value: "German"  }
                      ];
                      var arr3 = $.extendObjectArray(arr1, arr2, 'name');
                      
                      console.log(JSON.stringify(arr3, null, 2));
                      .as-console-wrapper { top: 0; max-height: 100% !important; }
                      &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

                      ES6 版本

                      (function($) {
                        $.extendObjectArray = (destArr, srcArr, key) => {
                          srcArr.forEach(srcObj => (existObj => {
                            if (existObj.length) {
                              $.extend(true, destArr[destArr.indexOf(existObj[0])], srcObj);
                            } else {
                              destArr.push(srcObj);
                            }
                          })(destArr.filter(v => v[key] === srcObj[key])));
                          return destArr;
                        };
                      })(jQuery);
                      

                      【讨论】:

                        【解决方案30】:

                        使用你想要的 lodash _.uniqBy

                        var arr3 = _.uniqBy(arr1.concat(arr2), 'name'); // es5
                        
                        let arr3 = _.uniqBy([...arr1, ...arr2], 'name'); // es6
                        

                        arr1、arr2 的顺序很重要!

                        请参阅文档https://lodash.com/docs/4.17.4#uniqBy

                        【讨论】:

                        • 需要使用第三方吗?
                        • 不,但它是实现它的最简洁的方式,它不仅仅是任何第三方,它的 lodash!
                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2019-09-04
                        • 1970-01-01
                        • 2022-01-21
                        • 2019-12-20
                        • 2019-03-13
                        • 1970-01-01
                        • 2022-01-03
                        相关资源
                        最近更新 更多