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

如何在JavaScript中高效地合并两个对象数组并按属性过滤重复项?,javascript,arrays,Javascript,Arrays,我还没有掌握JavaScript,我想做与本问题()相同的事情,但是使用对象数组并基于唯一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

我还没有掌握JavaScript,我想做与本问题()相同的事情,但是使用对象数组并基于唯一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' }}
  ];
var-mezclarreglo=函数(数组){
var a=array.concat();
对于(变量i=0;i)

如何解决我的问题?

根据@Paolo Moretti的评论进行更新

看看

一个简单而有效的解决方案是像这样使用。.uniq

_.uniq(data1.concat(data2), false, 'hid')

查看此图。

当您可以使用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: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]});
}
现在我们来看表演:

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

在我的机器上
版本ANTOINEV1:15.000ms
versionAntoinev2:54.000ms
Vladimir版本:1749.000ms

这就是为什么避免n²复杂性很重要的原因

函数合并(o,n){
返回n.concat(o).过滤器(函数(x,i,all){
return!all.some(函数y,j){
返回x.hid==y.hid&&j>i;
});
});
}
var old=[{
hid:'MTQZNTC1OTCYMZK1ODI3OTMJI3NDCYNZC0NJG0NDI5',
编号:“1”,
有效载荷:{
样式:“WebView”,
类型:“类型1”
}
}, {
hid:'MTQZNTC1OTCZMDG1MDGWTCWNZG3NJM4MDUZMJK3OTK3',
编号:'2',
有效载荷:{
样式:“WebView”,
类型:“类型1”
}
}, {
hid:'MTQzNTc1OTczNDMxNzQ1NDI2NzUwOTA0ODgwNDY0MDc3',
编号:'3',
有效载荷:{
样式:“WebView”,
类型:“类型1”
}
}];
变量ne=[{
hid:'MTQzNTc1OTczNDMxNzQ1NDI2NzUwOTA0ODgwNDY0MDc3',
编号:'3',
有效载荷:{
风格:假,
类型:false
}
}, {
hid:'MTQzNTc1OTc0NzcxNDM1MDUyMzA5MzQ4MjQ3OTQ1MzA5',
编号:'4',
有效载荷:{
样式:“WebView”,
类型:“类型1”
}
}];

document.write(“”+JSON.stringify(merge(ne,old),null,'\t')+“”);
首先,我喜欢这样的问题,谢谢你的提问。我喜欢把这看作是散列冲突问题(其中hid是“散列”)。你可以创建一个如下的函数:

mergeWithoutDups(ar1, ar2, ar3, ar4, ...)
结果是一个数组,其中的顺序由hid维护,其中的项由hid唯一。此外,由于所有数组只迭代一次,因此应该执行此操作。注意:如果希望新项优先于旧项,则应使用位于参数列表前面的新数组来调用它。例如

不过,对于@Stoyan的回应,下划线.js得到了广泛支持,并且可能有一个相当优化的
uniq
函数。如果您的项目允许,我建议使用它


干杯!

所以你需要更改
var new=
,因为
new
是一个保留字。另外,你需要保持结果的顺序吗?@Mike最好保持顺序,但不是必需的。ES6已经设置了你要找的内容,我想,请检查这个答案,尤其是侧边栏中有指向p的链接olyfill和其他一些预构建工具在您的情况下,您可以使用hid属性作为键,然后使用对象作为值。这不会返回对象数组。您的意思是类似于
\uuuq.uniq(data1.concat(data2),false,“hid”)
?很好。相应地进行了更新。我同意,将数组写入对象是一种更快的方法,但如果您不仅需要使用id进行合并呢?这样我的解决方案更紧凑、更可扩展。但为您提供了一个
+
。我添加了一个能够将多个属性用作唯一键的版本。
function mergeWithoutDups() {
  var merged = [],
    map = {};
  for(var i = 0; i < arguments.length; i++) {
    for(var j = 0; j < array.length; j++) {
      var item = array[j];
      var hid = item.hid;

      if(!map[hid]) {
        map[hid] = true;
        merged.push(item);
      }
    }
  }

  return merged;
}
mergeWithoutDups(ar1, ar2, ar3, ar4, ...)
mergeWithoutDups(newArray, oldArray)