javascript - 如何在 JavaScript 中有效地合并两个对象数组并按属性过滤重复项?

标签 javascript arrays

我还没有掌握 JavaScript,我想做与这个问题 (How to merge two arrays in Javascript and de-duplicate items) 相同的事情,但使用对象数组并根据唯一 ID 属性过滤重复项。

我已经用那个问题的答案之一做到了,但效率很低。

这是我的解决方案:

var mezclaArreglo = function (array) {
  var a = array.concat();
  for(var i=0; i<a.length; ++i) {
    for(var j=i+1; j<a.length; ++j) {
      if(a[i].hid === a[j].hid)
        a.splice(j--, 1);
    }
  }

  return a;
};

var old = 
  [{ hid: 'MTQzNTc1OTcyMzk1ODI3OTMyMjI3NDcyNzc0Njg0NDI5',
     number: '1',
     payload: { style: 'WebView', type: 'type1' }},
   { hid: 'MTQzNTc1OTczMDA1MDgwMTcwNzg3NjM4MDUzMjk3OTk3',
     number: '2',
     payload: { style: 'WebView', type: 'type1' }},
   { hid: 'MTQzNTc1OTczNDMxNzQ1NDI2NzUwOTA0ODgwNDY0MDc3',
     number: '3',
     payload: { style: 'WebView', type: 'type1' }}
   ];

var newA =
  [{ hid: 'MTQzNTc1OTczNDMxNzQ1NDI2NzUwOTA0ODgwNDY0MDc3',
     number: '3',
     payload: { style: false, type: false }},
   { hid: 'MTQzNTc1OTc0NzcxNDM1MDUyMzA5MzQ4MjQ3OTQ1MzA5',
     number: '4',
     payload: { style: 'WebView', type: 'type1' }}
  ];

// RESULT ARRAY
  [{ hid: 'MTQzNTc1OTcyMzk1ODI3OTMyMjI3NDcyNzc0Njg0NDI5',
     number: '1',
     payload: { style: 'WebView', type: 'type1' }},
   { hid: 'MTQzNTc1OTczMDA1MDgwMTcwNzg3NjM4MDUzMjk3OTk3',
     number: '2',
     payload: { style: 'WebView', type: 'type1' }},
   { hid: 'MTQzNTc1OTczNDMxNzQ1NDI2NzUwOTA0ODgwNDY0MDc3',
     number: '3',
     payload: { style: 'WebView', type: 'type1' }},
   { hid: 'MTQzNTc1OTc0NzcxNDM1MDUyMzA5MzQ4MjQ3OTQ1MzA5',
     number: '4',
     payload: { style: 'WebView', type: 'type1' }}
  ];

我需要以最有效的方式从 数组而不是 数组中删除重复的对象。

也许解决方案是使用此答案中的过滤器方法? ( https://stackoverflow.com/a/23080662/4275425 ) 我该如何为我的问题实现它?

最佳答案

当您可以使用 3n 复杂度时,您的解决方案复杂度为 :

var mergeWithoutDouble = function(array1, array2) {
    var mapHuidElement = {};

    for(var i = 0; i < array1.length; i ++){
        if(!mapHuidElement[array1[i]['huid']]){
            mapHuidElement[array1[i]['huid']] = array1[i];
        }
    }

    for(var i = 0; i < array2.length; i ++){
        if(!mapHuidElement[array2[i]['huid']]){
            mapHuidElement[array2[i]['huid']] = array2[i];
        }
    }

    var arrayMerged = Object.keys(mapHuidElement).map(function (key) {return mapHuidElement[key]});

    return arrayMerged;
}

注意:您可以将 huid 作为参数使其更通用,我认为我们也可以对其进行一些优化。

例子:

mergeWithoutDouble([{huid: 1}, {huid: 3}], [{huid: 2}, {huid: 3}]);

=> [{huid: 1}, {huid: 2}, {huid: 3}]

编辑:将多个属性作为唯一键:如果我们想将多个属性用作唯一键。

var mergeWithoutDouble = function(array1, array2, uniqueKeys) {
    var mapHuidElement = {};

    for(var i = 0; i < Math.max( array1.length, array2.length ) ; i ++){
        var a = i < array1.length,
            b = i < array2.length,
            key;
        if(a){
            key = "";
            for(var k = 0; k < uniqueKeys.length; k++){
                key += uniqueKeys[k]+":"+array1[i][uniqueKeys[k]]+";";
            }
            if(!mapHuidElement[key]){
                mapHuidElement[key] = array1[i];
            }
        } 
        if(b){
            key = "";
            for(var k = 0; k < uniqueKeys.length; k++){
                key += uniqueKeys[k]+":"+array2[i][uniqueKeys[k]]+";";
            }
            if(!mapHuidElement[key]){
                mapHuidElement[key] = array2[i];
            }
        }
    }

    return Object.keys(mapHuidElement).map(function (key) {return mapHuidElement[key]});
}

示例:

mergeWithoutDouble([{huid: 1, name: 'A'}, {huid: 1, name: 'B'}, {huid: 3, name:'A'}], [{huid: 2, 姓名: 'A'}, {huid: 3, 姓名: 'A'}], ['huid', '姓名']);

=> [{huid: 1, name: 'A'}, {huid: 1, name: 'B'}, {huid: 3, name:'A'}, {huid: 2,名称:'A'}]

精简版:

var mergeWithoutDouble=function(t,e,r){for(var n={},a=0;a<Math.max(t.length,e.length);a++){var h,f=a<t.length,g=a<e.length;if(f){h="";for(var l=0;l<r.length;l++)h+=r[l]+":"+t[a][r[l]]+";";n[h]||(n[h]=t[a])}if(g){h="";for(var l=0;l<r.length;l++)h+=r[l]+":"+e[a][r[l]]+";";n[h]||(n[h]=e[a])}}return Object.keys(n).map(function(t){return n[t]})};

现在让我们看看性能:

2 个包含 10000 个元素的数组,重复 10 次(1 个键:huid)。

On my machine
versionAntoinev1: 15.000ms
versionAntoinev2: 54.000ms
versionVladimir: 1749.000ms

这就是避免 n² 复杂度很重要的原因。

Plunker

关于javascript - 如何在 JavaScript 中有效地合并两个对象数组并按属性过滤重复项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31165919/

相关文章:

Javascript 正则表达式 - 捕获前面有另一个字符串的字符串

javascript - 在 Protractor 中定位父元素的推荐方法

javascript - 为什么jQuery或诸如getElementById之类的DOM方法找不到元素?

javascript - 通过 xml 将数据从一个数据库传递到另一个数据库

javascript - 你如何发送一个数组作为(jquery)ajax请求的一部分

python - 在两个 numpy 形状对象数组上应用成对形状函数

php - 比较数组键并创建 MySQL 语句的方法

javascript - 不同的 JavaScript 函数格式

javascript - Typescript 对象返回数组对象值错误 [Angular]

PHP 使用数组值截断和删除问题