我有两个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中合并两个数组,以便从每个数组中只获得唯一的项目,其顺序与它们插入原始数组的顺序相同?
当前回答
只是把我的两分钱扔进去。
function mergeStringArrays(a, b){
var hash = {};
var ret = [];
for(var i=0; i < a.length; i++){
var e = a[i];
if (!hash[e]){
hash[e] = true;
ret.push(e);
}
}
for(var i=0; i < b.length; i++){
var e = b[i];
if (!hash[e]){
hash[e] = true;
ret.push(e);
}
}
return ret;
}
这是我经常使用的方法,它使用一个对象作为哈希查找表来执行重复检查。假设哈希值是O(1),那么这将在O(n)中运行,其中n是a.length+b.length。老实说,我不知道浏览器是如何进行哈希的,但它在数千个数据点上表现良好。
其他回答
表演
今天2020.10.15我在Chrome v86、Safari v13.1.2和Firefox v81上对MacOs HighSierra 10.13.6进行了测试,以确定所选的解决方案。
后果
适用于所有浏览器
解决方案H快速/最快解决方案L很快解决方案D在大型阵列的chrome上速度最快解决方案G在小阵列上速度很快解决方案M对于小型阵列来说是最慢的解决方案E对于大型阵列来说是最慢的
细节
我执行两个测试用例:
对于2元素数组-您可以在此处运行对于10000个元素数组-您可以在这里运行
关于解决方案A.BCDEGHJLM在下面的片段中显示
// https://stackoverflow.com/a/10499519/860099函数A(arr1,arr2){返回_并集(arr1,arr2)}// https://stackoverflow.com/a/53149853/860099函数B(arr1,arr2){return _.unionWith(arr1,arr2,_.isEqual);}// https://stackoverflow.com/a/27664971/860099函数C(arr1,arr2){return[…new Set([…arr1,…arr2])]}// https://stackoverflow.com/a/48130841/860099函数D(arr1,arr2){return Array.from(新集合(arr1.concat(arr2)))}// https://stackoverflow.com/a/23080662/860099函数E(arr1,arr2){return arr1.concat(arr2.filter((项)=>arr1.indexOf(项)<0))}// https://stackoverflow.com/a/28631880/860099函数G(arr1,arr2){var哈希={};变量i;对于(i=0;i<arr1.length;i++){hash[arr1[i]=真;}对于(i=0;i<arr2.length;i++){hash[ar2[i]=真;}return Object.keys(哈希);}// https://stackoverflow.com/a/13847481/860099函数H(a,b){var哈希={};var ret=[];对于(var i=0;i<a.length;i++){变量e=a[i];if(!hash[e]){hash[e]=真;ret.push(e);}}对于(var i=0;i<b.length;i++){变量e=b[i];if(!hash[e]){hash[e]=真;ret.push(e);}}返回ret;}// https://stackoverflow.com/a/1584377/860099函数J(arr1,arr2){函数arrayUnique(数组){var a=array.contat();对于(var i=0;i<a.length;++i){对于(var j=i+1;j<a.length;++j){如果(a[i]===a[j])a.接头(j-,1);}}返回a;}return arrayUnique(arr1.concat(arr2));}// https://stackoverflow.com/a/25120770/860099函数L(array1,array2){常量数组3=数组1.slice(0);设len1=阵列长度;设len2=阵列2.length;常量assoc={};而(len1--){assoc[array1[len1]]=空;}而(len2--){设itm=array2[len2];if(assoc[itm]==未定义){//消除indexOf调用array3.push(itm);assoc[itm]=空;}}返回数组3;}// https://stackoverflow.com/a/39336712/860099函数M(arr1,arr2){常量comp=f=>g=>x=>f(g(x));常量应用=f=>a=>f(a);常量flip=f=>b=>a=>f(a)(b);常量concat=xs=>y=>xs.contat(y);const afrom=应用(Array.from);const createSet=xs=>新集合(xs);常量过滤器=f=>xs=>xs.filter(apply(f));常量重复数据删除=comp(afrom)(createSet);常量并集=xs=>ys=>{const zs=创建集(xs);返回凹面(xs)(滤波器(x=>zs.has(x)? 假的:zs.add(x))(ys));}返回联合(重复数据消除(arr1))(arr2)}// -------------//测试// -------------var array1=[“Vijendra”,“Singh”];var array2=[“Singh”,“Shakya”];[A、B、C、D、E、G、H、J、L、M]。对于每个(f=>{console.log(`${f.name}[${f([…array1],[…array2])}]`);})<script src=“https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js“integrity=”sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==“crossrorigin=”匿名“></script>此代码段仅显示性能测试中使用的函数-它本身不执行测试!
下面是chrome的示例测试运行
更新
我删除了案例F、I、K,因为它们修改了输入数组,基准测试给出了错误的结果
下面是使用Set的另一个简单解决方案:
常量o1={a:1};const arr1=['!@#$%^&*()','gh',123,o1,1,true,undefined,null];常量arr2=['!@#$%^&*()',123,'abc',o1,0x001,true,void 0,0];const mergeUnique=(…args)=>[…新集合([].contat(…arg))];console.log(mergeUnique(arr1,arr2));
使用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。
如果您有非常大的列表,则不执行此操作,因为已经记录了许多解决方案,所以这不适合合并,但我用此解决方案解决了我的问题(因为大多数数组过滤解决方案都适用于简单数组)
const uniqueVehiclesServiced =
invoice.services.sort().filter(function(item, pos, ary) {
const firstIndex = invoice.services.findIndex((el, i, arr) => el.product.vin === item.product.vin)
return !pos || firstIndex == pos;
});
DeDuplicate单个或Merge和DeDupliplicate多个数组输入。示例如下。
使用ES6-设置,用于,销毁
我编写了一个接受多个数组参数的简单函数。与上面的解决方案几乎相同,只是有更实际的用例。此函数不会将重复的值连接到一个数组中,以便在稍后阶段删除它们。
短功能定义(仅9行)
/**
* This function merging only arrays unique values. It does not merges arrays in to array with duplicate values at any stage.
*
* @params ...args Function accept multiple array input (merges them to single array with no duplicates)
* it also can be used to filter duplicates in single array
*/
function arrayDeDuplicate(...args){
let set = new Set(); // init Set object (available as of ES6)
for(let arr of args){ // for of loops through values
arr.map((value) => { // map adds each value to Set object
set.add(value); // set.add method adds only unique values
});
}
return [...set]; // destructuring set object back to array object
// alternativly we culd use: return Array.from(set);
}
使用示例代码笔:
// SCENARIO
let a = [1,2,3,4,5,6];
let b = [4,5,6,7,8,9,10,10,10];
let c = [43,23,1,2,3];
let d = ['a','b','c','d'];
let e = ['b','c','d','e'];
// USEAGE
let uniqueArrayAll = arrayDeDuplicate(a, b, c, d, e);
let uniqueArraySingle = arrayDeDuplicate(b);
// OUTPUT
console.log(uniqueArrayAll); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 43, 23, "a", "b", "c", "d", "e"]
console.log(uniqueArraySingle); // [4, 5, 6, 7, 8, 9, 10]