2017-10-22 125 views
1

使用平面列表并寻找一种有效的方法来组合列表元素,同时删除重复的元素。每个元素都有一个唯一的键值,以知道它是否是重复的。最有效的方法来合并数组删除重复

我目前的执行力度使用concat功能:

Array.prototype.unique = function() { 
     var a = this.concat(); 
     for(var i=0; i<a.length; ++i) { 
      for(var j=i+1; j<a.length; ++j) { 
       if(a[i].key === a[j].key) 
        a.splice(j--, 1); 
      } 
     } 
     return a; 
    }; 

const OldArray = this.state.data; 
const NewArray = [] //contains values we loaded in 
const FinalArray = OldArray.concat(NewArray).unique(); 

//Update the State 
this.setState({ 
    data: FinalArray 
)} 

这绝对作品,但每到这个函数运行其至少N^2的效率,这似乎是坏的。有一个更好的方法吗?我觉得必须有..

回答

2

您可以使用Array#reduce来创建唯一值的Map,然后将其传回给数组。这将使您获得具有相同键的对象的第一次出现。

const union = (arr1, arr2, key) => [... // spread to an array 
 
    arr1.concat(arr2) // concat the arrays 
 
    .reduce((m, o) => m.has(o[key]) ? m : m.set(o[key], o), new Map) // reduce to a map by value of key 
 
    .values()]; // get the values iterator 
 

 
const OldArray = [{ a: 1, v: 1 }, { a: 2 }] 
 
const NewArray = [{ a: 1, v: 100 }, { a: 3 }] 
 
const FinalArray = union(OldArray, NewArray, 'a') 
 

 
console.log(FinalArray);

另一种选择,如@ 4castle建议,是使用阵列#地图初始化地图。但是,这将使具有相同键的对象的最后一次出现。在初始化Map之前,您总是可以Array#反转数组。

const union = (arr1, arr2, key) => [... // spread to an array 
 
    new Map(arr1.concat(arr2).map(o => [o[key], o])) // concat and initialize the map 
 
    .values()]; // get the values iterator 
 

 
const OldArray = [{ a: 1, v: 1 }, { a: 2 }] 
 
const NewArray = [{ a: 1, v: 100 }, { a: 3 }] 
 
const FinalArray = union(OldArray, NewArray, 'a') 
 

 
console.log(FinalArray);

+0

'新地图(arr1.concat(ARR2).MAP(O => [问题o [键],O]))'也可以用于创建'Map'。 – 4castle

+0

确实。但是,有一点警告。查看更新的答案。 –