我有两个JavaScript数组:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
我希望输出为:
var array3 = ["Vijendra","Singh","Shakya"];
输出数组应删除重复的单词。
如何在JavaScript中合并两个数组,以便从每个数组中只获得唯一的项目,其顺序与它们插入原始数组的顺序相同?
我有两个JavaScript数组:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
我希望输出为:
var array3 = ["Vijendra","Singh","Shakya"];
输出数组应删除重复的单词。
如何在JavaScript中合并两个数组,以便从每个数组中只获得唯一的项目,其顺序与它们插入原始数组的顺序相同?
当前回答
[...array1,...array2] // => don't remove duplication
OR
[...new Set([...array1 ,...array2])]; // => remove duplication
其他回答
之前写过同样的原因(适用于任意数量的数组):
/**
* Returns with the union of the given arrays.
*
* @param Any amount of arrays to be united.
* @returns {array} The union array.
*/
function uniteArrays()
{
var union = [];
for (var argumentIndex = 0; argumentIndex < arguments.length; argumentIndex++)
{
eachArgument = arguments[argumentIndex];
if (typeof eachArgument !== 'array')
{
eachArray = eachArgument;
for (var index = 0; index < eachArray.length; index++)
{
eachValue = eachArray[index];
if (arrayHasValue(union, eachValue) == false)
union.push(eachValue);
}
}
}
return union;
}
function arrayHasValue(array, value)
{ return array.indexOf(value) != -1; }
编辑:
只有在项目很少的情况下,第一种解决方案才是最快的。当项目超过400项时,Set解决方案将变得最快。当有100000个项目时,它比第一个解决方案快一千倍。
考虑到只有当有很多项时,性能才是重要的,而且Set解决方案是迄今为止最可读的,在大多数情况下,它应该是正确的解决方案
以下性能结果是用少量项目计算的
基于jsperf,将两个数组合并为一个新数组的最快方法(编辑:如果少于400项)如下:
for (var i = 0; i < array2.length; i++)
if (array1.indexOf(array2[i]) === -1)
array1.push(array2[i]);
这个慢17%:
array2.forEach(v => array1.includes(v) ? null : array1.push(v));
这个速度慢45%(编辑:当项目少于100个时。当项目较多时,速度快得多):
var a = [...new Set([...array1 ,...array2])];
而被接受的答案要慢55%(而且写起来要长得多)(编辑:当有10万个项目时,它比任何其他方法都慢几个数量级)
var a = array1.concat(array2);
for (var i = 0; i < a.length; ++i) {
for (var j = i + 1; j < a.length; ++j) {
if (a[i] === a[j])
a.splice(j--, 1);
}
}
https://jsperf.com/merge-2-arrays-without-duplicate
使用Lodash
我发现@GijsjanB的答案很有用,但我的数组包含具有许多属性的对象,因此我不得不使用其中一个属性来消除它们的重复。
这是我使用lodash的解决方案
userList1 = [{ id: 1 }, { id: 2 }, { id: 3 }]
userList2 = [{ id: 3 }, { id: 4 }, { id: 5 }]
// id 3 is repeated in both arrays
users = _.unionWith(userList1, userList2, function(a, b){ return a.id == b.id });
// users = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }]
作为第三个参数传递的函数有两个参数(两个元素),如果它们相等,则必须返回true。
我有一个类似的请求,但它具有数组中元素的Id。
这里是我进行重复数据消除的方法。
它简单,易于维护,使用方便。
// Vijendra's Id = Id_0
// Singh's Id = Id_1
// Shakya's Id = Id_2
let item0 = { 'Id': 'Id_0', 'value': 'Vijendra' };
let item1 = { 'Id': 'Id_1', 'value': 'Singh' };
let item2 = { 'Id': 'Id_2', 'value': 'Shakya' };
let array = [];
array = [ item0, item1, item1, item2 ];
let obj = {};
array.forEach(item => {
obj[item.Id] = item;
});
let deduplicatedArray = [];
let deduplicatedArrayOnlyValues = [];
for(let [index, item] of Object.values(obj).entries()){
deduplicatedArray = [ ...deduplicatedArray, item ];
deduplicatedArrayOnlyValues = [ ...deduplicatedArrayOnlyValues , item.value ];
};
console.log( JSON.stringify(array) );
console.log( JSON.stringify(deduplicatedArray) );
console.log( JSON.stringify(deduplicatedArrayOnlyValues ) );
控制台日志
[{"recordId":"Id_0","value":"Vijendra"},{"recordId":"Id_1","value":"Singh"},{"recordId":"Id_1","value":"Singh"},{"recordId":"Id_2","value":"Shakya"}]
[{"recordId":"Id_0","value":"Vijendra"},{"recordId":"Id_1","value":"Singh"},{"recordId":"Id_2","value":"Shakya"}]
["Vijendra","Singh","Shakya"]
构建一个测试人员来检查一些面向性能的答案的速度。请随意添加更多内容。到目前为止,Set是最简单和最快的选项(随着记录数量的增加,它的边距会更大),至少对于简单的number类型来说是如此。
常量记录=10000,//每个阵列的最大记录数max_int=100,//每个数组的最大整数值dup_rate=.5//复制率让perf={},//性能记录器,ts=0,te=0,array1=[],//初始化数组array2=[],array1b=[],array2b=[],a=[];//填充随机化数组for(设i=0;i<记录;i++){设r=Math.random(),n=r*max_int;如果(Math.random()<.5){array1.push(n);r<dup_rate&&array2.push(n);}其他{阵列2.push(n);r<dup_rate&&array1.push(n);}}//缺少rfdc的简单深度副本,以防有人想要使用更复杂的数据类型进行测试array1b=JSON.parse(JSON.stringify(array1));array2b=JSON.parse(JSON.stringfy(array2));console.log('数组1中的记录:',array1.length,array1b.length);console.log('数组2中的记录:',array2.length,array2b.length);//试验方法1(jsperf per@Pitouli)ts=performance.now();for(设i=0;i<array2.length;i++)如果(array1.indexOf(array2[i])==-1)array1.push(array2[i])//修改数组1te=performance.now();perf.m1=te-ts;console.log('方法1合并',array1.length,'记录在:',perf.m1);array1=JSON.parse(JSON.stringify(array1b))//重置阵列1//测试方法2(经典的Each)ts=performance.now();array2.forEach(v=>array1.includes(v)?null:array1.push(v))//修改数组1te=performance.now();perf.m2=te-ts;console.log('方法2合并',array1.length,'记录在:',perf.m2中);//测试方法3(最简单的本机选项)ts=performance.now();a=[…新集合([…array1,…array2])]//不修改源阵列te=performance.now();perf.m3=te-ts;console.log('方法3合并',a.length,'记录在:',perf.m3);//测试方法4(选定答案)ts=performance.now();a=阵列1.concat(阵列2)//不修改源阵列for(设i=0;i<a.length;++i){for(设j=i+1;j<a.length;++j){如果(a[i]===a[j])a.接头(j-,1);}}te=performance.now();perf.m4=te-ts;console.log('Method 4 merged',a.length,'records in:',perf.m4);//试验方法5(@Kamil Kielczewski)ts=performance.now();函数K(arr1,arr2){设r=[],h={};而(arr1.length){设e=arr1.shift()//修改数组1如果(!h[e])h[e]=1&&r.push(e);}而(arr2.长度){设e=arr2.shift()//修改数组2如果(!h[e])h[e]=1&&r.push(e);}返回r;}a=K(阵列1,阵列2);te=performance.now();perf.m5=te-ts;console.log('Method 5 merged',a.length,'records in:',perf.m4);array1=JSON.parse(JSON.stringify(array1b))//重置阵列1array2=JSON.parse(JSON.stringfy(array2b))//重置阵列2for(设i=1;i<6;i++){console.log('方法:',i,'速度为',(perf[m'+i]/perf.m1*100).toFixed(2),'方法1的%');}