How to merge two arrays in JavaScript and de-duplicate items
我有两个javascript数组:
1 2 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; |
我希望输出为:
1 | var array3 = ["Vijendra","Singh","Shakya"]; |
输出数组应删除重复的字。
如何在javascript中合并两个数组,以便仅从每个数组中按插入原始数组的相同顺序获取唯一项?
只合并数组(不删除重复项)
ES5版本使用1 2 3 4 5 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = array1.concat(array2); // Merges both arrays // [ 'Vijendra', 'Singh', 'Singh', 'Shakya' ] |
ES6版本使用销毁
1 2 3 | const array1 = ["Vijendra","Singh"]; const array2 = ["Singh","Shakya"]; const array3 = [...array1, ...array2]; |
由于没有"内置"方式来删除重复项(ECMA-262实际上有
1 2 3 4 5 6 7 8 9 10 11 | 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] === a[j]) a.splice(j--, 1); } } return a; }; |
然后,要使用它:
1 2 3 4 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; // Merges both arrays and gets unique items var array3 = array1.concat(array2).unique(); |
这还将保留数组的顺序(即,不需要排序)。
由于许多人对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function arrayUnique(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] === a[j]) a.splice(j--, 1); } } return a; } var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; // Merges both arrays and gets unique items var array3 = arrayUnique(array1.concat(array2)); |
对于那些有幸在ES5可用的浏览器上工作的人,您可以这样使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Object.defineProperty(Array.prototype, 'unique', { enumerable: false, configurable: false, writable: false, value: 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] === a[j]) a.splice(j--, 1); } } return a; } }); |
使用underline.js或lo dash,可以执行以下操作:
1 2 | _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); => [1, 2, 3, 101, 10] |
http://underlinejs.org/联合
http://lodash.com/docs联合
首先连接两个数组,然后只筛选出唯一的项。
1 2 3 4 5 | var a = [1, 2, 3], b = [101, 2, 1, 10]; var c = a.concat(b); var d = c.filter(function (item, pos) {return c.indexOf(item) == pos}); // d is [1,2,3,101,10] |
http://jsfiddle.net/simo/98622/
编辑正如@dmitry所建议的(见下面的第二条注释),更明智的解决方案是在与
1 2 3 4 5 6 | var a = [1, 2, 3], b = [101, 2, 1, 10]; var c = a.concat(b.filter(function (item) { return a.indexOf(item) < 0; })); // d is [1,2,3,101,10] |
这是一个使用排列运算符和数组泛型的ECMAScript 6解决方案。
目前它只适用于Firefox,也可能是Internet Explorer技术预览版。
但是如果你用巴别塔,你现在就可以吃了。
1 2 3 4 5 6 | // Input: [ [1, 2, 3], [101, 2, 1, 10], [2, 1] ] // Output: [1, 2, 3, 101, 10] function mergeDedupe(arr) { return [...new Set([].concat(...arr))]; } |
ES6
1 | array1.push(...array2) // => don't remove duplication |
或
1 | [...array1,...array2] // => don't remove duplication |
或
1 | [...new Set([...array1 ,...array2])]; // => remove duplication |
使用一套(EcmaScript 2015),它将简单到:
1 2 3 | const array1 = ["Vijendra","Singh"]; const array2 = ["Singh","Shakya"]; const array3 = Array.from(new Set(array1.concat(array2))); |
这里是一个稍微不同的环。利用最新版本的chrome中的一些优化,它是解决两个数组联合的最快方法(chrome 38.0.2111)。
http://jspef.com/merge-two-array-keeping-only-unique-values
1 2 3 4 5 6 7 8 9 10 11 12 13 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = []; var arr = array1.concat(array2), len = arr.length; while (len--) { var itm = arr[len]; if (array3.indexOf(itm) === -1) { array3.unshift(itm); } } |
while循环:~589k ops/s
过滤器:~445K ops/s
洛达什:308k ops/s
对于回路:225k ops/s
一条评论指出,我的一个设置变量导致我的循环领先于其他变量,因为它不需要初始化一个空数组来写入。我同意这一点,所以我重写了测试,甚至在比赛场地,并包括一个更快的选择。
http://jspef.com/merge-two-array-keeping-only-unique-values/52
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | let whileLoopalt=function (array1, array2) { const array3 = array1.slice(0); let len1 = array1.length; let len2 = array2.length; const assoc = {}; while (len1--) { assoc[array1[len1]] = null; } while (len2--) { let itm = array2[len2]; if (assoc[itm] === undefined) { // Eliminate the indexOf call array3.push(itm); assoc[itm] = null; } } return array3; }; |
在这个替代解决方案中,我结合了一个答案的关联数组解决方案,以消除循环中的
在这里,每个值(i-1)上的双循环的最高答案仍然明显较慢。罗达什仍然做得很好,我仍然会向任何不介意在他们的项目中添加图书馆的人推荐它。对于那些不想这样做的人来说,我的while循环仍然是一个很好的答案,过滤器的答案在这里有一个很强的显示,在我的测试中用最新的淡黄色(44.0.2360)打败了所有人。
如果你想提高速度的话,看看迈克的答案和丹·斯托克的答案。在浏览了几乎所有可行的答案之后,这些都是迄今为止所有结果中最快的。
您只需使用ecmascript 6,
1 2 3 4 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = [...new Set([...array1 ,...array2])]; console.log(array3); // ["Vijendra","Singh","Shakya"]; |
- 使用排列运算符连接数组。
- 使用set创建一组不同的元素。
- 再次使用Spread运算符将集合转换为数组。
合并两个数组并删除ES6中的重复项
1 2 3 4 5 | let arr1 = [3, 5, 2, 2, 5, 5]; let arr2 = [2, 1, 66, 5]; let unique = [...new Set([...arr1,...arr2])]; console.log(unique); // [ 3, 5, 2, 1, 66 ] |
1 2 3 4 5 6 7 8 9 10 11 | Array.prototype.merge = function(/* variable number of arrays */){ for(var i = 0; i < arguments.length; i++){ var array = arguments[i]; for(var j = 0; j < array.length; j++){ if(this.indexOf(array[j]) === -1) { this.push(array[j]); } } } return this; }; |
更好的数组合并函数。
只需避开嵌套循环(o(n^2))和
1 2 3 4 5 6 7 8 9 10 | function merge(a, b) { var hash = {}, i; for (i=0; i<a.length; i++) { hash[a[i]]=true; } for (i=0; i<b.length; i++) { hash[b[i]]=true; } return Object.keys(hash); } |
就把我的两分钱投进去。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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。老实说,我不知道浏览器是如何处理散列的,但是它在数千个数据点上运行得很好。
你为什么不用物体?看起来你在模拟一个场景。然而,这并不能维持秩序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | var set1 = {"Vijendra":true,"Singh":true} var set2 = {"Singh":true, "Shakya":true} // Merge second object into first function merge(set1, set2){ for (var key in set2){ if (set2.hasOwnProperty(key)) set1[key] = set2[key] } return set1 } merge(set1, set2) // Create set from array function setify(array){ var result = {} for (var item in array){ if (array.hasOwnProperty(item)) result[array[item]] = true } return result } |
基于ES6的联合解决方案
1 2 3 4 | let arr1 = [1,2,3,4,5]; let arr2 = [3,4,5,6]; let result = [...new Set([...arr1, ...arr2])]; console.log(result); |
简化了Simo的答案,并将其转化为一个很好的函数。
1 2 3 4 5 | function mergeUnique(arr1, arr2){ return arr1.concat(arr2.filter(function (item) { return arr1.indexOf(item) === -1; })); } |
最佳解决方案…
您可以直接在浏览器控制台中点击…
无副本1 2 3 4 5 6 | a = [1, 2, 3]; b = [3, 2, 1,"prince"]; a.concat(b.filter(function(el) { return a.indexOf(el) === -1; })); |
带复制品
1 | ["prince","asish", 5].concat(["ravi", 4]) |
如果你不想重复,你可以从这里尝试一个更好的解决方案——喊代码。
1 2 3 | [1, 2, 3].concat([3, 2, 1,"prince"].filter(function(el) { return [1, 2, 3].indexOf(el) === -1; })); |
试用Chrome浏览器控制台
1 | f12 > console |
输出:
1 2 3 | ["prince","asish", 5,"ravi", 4] [1, 2, 3,"prince"] |
我的一个半便士:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Array.prototype.concat_n_dedupe = function(other_array) { return this .concat(other_array) // add second .reduce(function(uniques, item) { // dedupe all if (uniques.indexOf(item) == -1) { uniques.push(item); } return uniques; }, []); }; var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var result = array1.concat_n_dedupe(array2); console.log(result); |
只需使用underline.js的=>uniq即可实现:
1 2 3 | array3 = _.uniq(array1.concat(array2)) console.log(array3) |
它将打印["Vijendra"、"Singh"、"Shakya"]。
它可以用set来完成。
1 2 3 4 5 6 7 8 9 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = array1.concat(array2); var tempSet = new Set(array3); array3 = Array.from(tempSet); //show output document.body.querySelector("div").innerHTML = JSON.stringify(array3); |
1 | temp text |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | //Array.indexOf was introduced in javascript 1.6 (ECMA-262) //We need to implement it explicitly for other browsers, if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(elt, from) { var len = this.length >>> 0; for (; from < len; from++) { if (from in this && this[from] === elt) return from; } return -1; }; } //now, on to the problem var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var merged = array1.concat(array2); var t; for(i = 0; i < merged.length; i++) if((t = merged.indexOf(i + 1, merged[i])) != -1) { merged.splice(t, 1); i--;//in case of multiple occurrences } |
其他浏览器的
1 | array1.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos) |
这个方法的好处在于性能,一般来说,在处理数组时,您都是链接方法,如过滤器、映射等,因此您可以添加该行,它将使用array1连接并消除array2的重复数据,而不需要引用后面的方法(当您没有链接方法时),例如:
1 2 3 4 5 6 7 8 9 10 | someSource() .reduce(...) .filter(...) .map(...) // and now you want to concat array2 and deduplicate: .concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos) // and keep chaining stuff .map(...) .find(...) // etc |
(我不想污染array.prototype,这是尊重这个链的唯一方法——定义一个新的函数会破坏它——所以我认为只有这样才能实现这个目标)
新的解决方案(使用
1 2 3 4 5 6 7 8 | Array.prototype.uniqueMerge = function( a ) { for ( var nonDuplicates = [], i = 0, l = a.length; i<l; ++i ) { if ( this.indexOf( a[i] ) === -1 ) { nonDuplicates.push( a[i] ); } } return this.concat( nonDuplicates ) }; |
用途:
1 2 | >>> ['Vijendra', 'Singh'].uniqueMerge(['Singh', 'Shakya']) ["Vijendra","Singh","Shakya"] |
array.prototype.indexof(用于Internet Explorer):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Array.prototype.indexOf = Array.prototype.indexOf || function(elt) { var len = this.length >>> 0; var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from): Math.floor(from); if (from < 0)from += len; for (; from < len; from++) { if (from in this && this[from] === elt)return from; } return -1; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Array.prototype.add = function(b){ var a = this.concat(); // clone current object if(!b.push || !b.length) return a; // if b is not an array, or empty, then return a unchanged if(!a.length) return b.concat(); // if original is empty, return b // go through all the elements of b for(var i = 0; i < b.length; i++){ // if b's value is not in a, then add it if(a.indexOf(b[i]) == -1) a.push(b[i]); } return a; } // Example: console.log([1,2,3].add([3, 4, 5])); // will output [1, 2, 3, 4, 5] |
- A modern way to achieve this is to simply use the spread operator.
- And to avoid duplication, we can efficiently use Sets; Sets won't allow duplicates by default.
- To get output as an array back from a Set, we can use Array.from()
下面是你的场景演示-
1 2 3 4 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var resArr = Array.from(new Set([...array1, ...array2])); console.log(resArr); |
对于ES6,只需一行:
1 2 3 | a = [1, 2, 3, 4] b = [4, 5] [...new Set(a.concat(b))] // [1, 2, 3, 4, 5] |
1 2 3 4 5 6 | var arr1 = [1, 3, 5, 6]; var arr2 = [3, 6, 10, 11, 12]; arr1.concat(arr2.filter(ele => !arr1.includes(ele))); console.log(arr1); output :- [1, 3, 5, 6, 10, 11, 12] |
为了这个…以下是单线解决方案:
1 2 | const x = [...new Set([['C', 'B'],['B', 'A']].reduce( (a, e) => a.concat(e), []))].sort() // ['A', 'B', 'C'] |
不太可读,但可能有助于某人:
在Dojo 1.6 +
1 2 3 4 5 6 7 8 9 | var unique = []; var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = array1.concat(array2); // Merged both arrays dojo.forEach(array3, function(item) { if (dojo.indexOf(unique, item) > -1) return; unique.push(item); }); |
更新
请参见工作代码。
http://jsfiddle.net/uaxja/1/
最简单的方法是使用
第一种方式:
1 2 3 4 5 6 | const firstArray = [1,2, 2]; const secondArray = [3,4]; // now lets merge them const mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4] //now use filter to remove dups const removeDuplicates = mergedArray.filter((elem, index) => mergedArray.indexOf(elem) === index); // [1,2,3, 4] |
第二种方法(但对用户界面有性能影响):
1 2 3 4 5 | const firstArray = [1,2, 2]; const secondArray = [3,4]; // now lets merge them const mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4] const removeDuplicates = new Set(mergedArray); |
合并无限数量的数组或非数组并保持其唯一性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | function flatMerge() { return Array.prototype.reduce.call(arguments, function (result, current) { if (!(current instanceof Array)) { if (result.indexOf(current) === -1) { result.push(current); } } else { current.forEach(function (value) { console.log(value); if (result.indexOf(value) === -1) { result.push(value); } }); } return result; }, []); } flatMerge([1,2,3], 4, 4, [3, 2, 1, 5], [7, 6, 8, 9], 5, [4], 2, [3, 2, 5]); // [1, 2, 3, 4, 5, 7, 6, 8, 9] flatMerge([1,2,3], [3, 2, 1, 5], [7, 6, 8, 9]); // [1, 2, 3, 5, 7, 6, 8, 9] flatMerge(1, 3, 5, 7); // [1, 3, 5, 7] |
假设原始数组不需要重复数据消除,这应该非常快,保持原始顺序,并且不修改原始数组…
1 2 3 4 5 6 7 8 9 | function arrayMerge(base, addendum){ var out = [].concat(base); for(var i=0,len=addendum.length;i<len;i++){ if(base.indexOf(addendum[i])<0){ out.push(addendum[i]); } } return out; } |
用途:
1 2 3 4 5 6 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = arrayMerge(array1, array2); console.log(array3); //-> [ 'Vijendra', 'Singh', 'Shakya' ] |
看来我的测试中接受的答案是最慢的;
注意,我正在按键合并两个对象数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> JS Bin </head> <body> <button type='button' onclick='doit()'>do it</button> function doit(){ var items = []; var items2 = []; var itemskeys = {}; for(var i = 0; i < 10000; i++){ items.push({K:i, C:"123"}); itemskeys[i] = i; } for(var i = 9000; i < 11000; i++){ items2.push({K:i, C:"123"}); } console.time('merge'); var res = items.slice(0); //method1(); method0(); //method2(); console.log(res.length); console.timeEnd('merge'); function method0(){ for(var i = 0; i < items2.length; i++){ var isok = 1; var k = items2[i].K; if(itemskeys[k] == null){ itemskeys[i] = res.length; res.push(items2[i]); } } } function method1(){ for(var i = 0; i < items2.length; i++){ var isok = 1; var k = items2[i].K; for(var j = 0; j < items.length; j++){ if(items[j].K == k){ isok = 0; break; } } if(isok) res.push(items2[i]); } } function method2(){ res = res.concat(items2); for(var i = 0; i < res.length; ++i) { for(var j = i+1; j < res.length; ++j) { if(res[i].K === res[j].K) res.splice(j--, 1); } } } } </body> </html> |
ES2015的功能方法
按照功能方法,两个
不管怎样,结合
1 2 3 4 5 6 | Array A + Array B [unique] + [unique] [duplicated] + [unique] [unique] + [duplicated] [duplicated] + [duplicated] |
前两个排列很容易用一个函数处理。但是,最后两个更复杂,因为只要依赖于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // small, reusable auxiliary functions const comp = f => g => x => f(g(x)); const apply = f => a => f(a); const flip = f => b => a => f(a) (b); const concat = xs => y => xs.concat(y); const afrom = apply(Array.from); const createSet = xs => new Set(xs); const filter = f => xs => xs.filter(apply(f)); // de-duplication const dedupe = comp(afrom) (createSet); // the actual union function const union = xs => ys => { const zs = createSet(xs); return concat(xs) ( filter(x => zs.has(x) ? false : zs.add(x) ) (ys)); } // mock data const xs = [1,2,2,3,4,5]; const ys = [0,1,2,3,3,4,5,6,6]; // here we go console.log("unique/unique", union(dedupe(xs)) (ys) ); console.log("duplicated/unique", union(xs) (ys) ); |
从这里开始,实现一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | // small, reusable auxiliary functions const uncurry = f => (a, b) => f(a) (b); const foldl = f => acc => xs => xs.reduce(uncurry(f), acc); const apply = f => a => f(a); const flip = f => b => a => f(a) (b); const concat = xs => y => xs.concat(y); const createSet = xs => new Set(xs); const filter = f => xs => xs.filter(apply(f)); // union and unionn const union = xs => ys => { const zs = createSet(xs); return concat(xs) ( filter(x => zs.has(x) ? false : zs.add(x) ) (ys)); } const unionn = (head, ...tail) => foldl(union) (head) (tail); // mock data const xs = [1,2,2,3,4,5]; const ys = [0,1,2,3,3,4,5,6,6]; const zs = [0,1,2,3,4,5,6,7,8,9]; // here we go console.log( unionn(xs, ys, zs) ); |
原来
带过滤器的最简单解决方案:
1 2 3 4 5 6 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var mergedArrayWithoutDuplicates = array1.concat( array2.filter(seccondArrayItem => !array1.includes(seccondArrayItem)) ); |
消除单个或合并多个阵列输入的重复数据。下面的例子。使用ES6-设置,用于,销毁
我编写了这个简单的函数,它接受多个数组参数。与上面的解决方案基本相同,它只是具有更实际的用例。此函数不会只将重复值连接到一个数组中,以便在以后的某个阶段删除它们。
短函数定义(仅9行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * 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); } |
使用代码笔示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 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] |
这很简单,可以使用jquery在一行中完成:
1 2 3 4 5 | var arr1 = ['Vijendra', 'Singh'], arr2 =['Singh', 'Shakya']; $.unique(arr1.concat(arr2))//one line ["Vijendra","Singh","Shakya"] |
1 2 3 4 5 6 7 8 | var array1 = ["one","two"]; var array2 = ["two","three"]; var collectionOfTwoArrays = [...array1, ...array2]; var uniqueList = array => [...new Set(array)]; console.log('Collection :'); console.log(collectionOfTwoArrays); console.log('Collection without duplicates :'); console.log(uniqueList(collectionOfTwoArrays)); |
如果不想复制特定属性(例如ID)
1 2 | let noDuplicate = array1.filter ( i => array2.findIndex(a => i.id==a.id)==-1 ); let result = [...noDuplicate, ...array2]; |
就计算时间而言,这是最有效的方法。它还保持元素的初始顺序。
首先过滤第二个数组中的所有重复项,然后将剩下的内容连接到第一个数组中。
1 2 3 4 5 6 | var a = [1,2,3]; var b = [5,4,3]; var c = a.concat(b.filter(function(i){ return a.indexOf(i) == -1; })); console.log(c); // [1, 2, 3, 5, 4] |
这里有一个稍微改进(更快)的IT版本,它的缺点是数组不能错过值:
1 2 3 4 5 | var i, c = a.slice(), ci = c.length; for(i = 0; i < b.length; i++){ if(c.indexOf(b[i]) == -1) c[ci++] = b[i]; } |
我学习了一种用spread操作符连接两个数组的冒失的小方法:
1 2 3 4 | var array1 = ['tom', 'dick', 'harry']; var array2 = ['martin', 'ricky']; array1.push(...array2); |
"…"Spread运算符将以下数组拆分为单个项,然后push可以将它们作为单独的参数处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 | var MergeArrays=function(arrayOne, arrayTwo, equalityField) { var mergeDictionary = {}; for (var i = 0; i < arrayOne.length; i++) { mergeDictionary[arrayOne[i][equalityField]] = arrayOne[i]; } for (var i = 0; i < arrayTwo.length; i++) { mergeDictionary[arrayTwo[i][equalityField]] = arrayTwo[i]; } return $.map(mergeDictionary, function (value, key) { return value }); } |
利用字典和jquery,您可以合并这两个数组,而不会得到重复的数组。在我的示例中,我在对象上使用了一个给定的字段,但可能只是对象本身。
下面是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 | var unique = function(array) { var unique = [] for (var i = 0; i < array.length; i += 1) { if (unique.indexOf(array[i]) == -1) { unique.push(array[i]) } } return unique } var uniqueList = unique(["AAPL","MSFT"].concat(["MSFT","BBEP","GE"])); |
我们定义
这是我的第二个答案,但我相信最快的答案?我希望有人能帮我检查一下并在评论中回复。
我的第一次尝试达到了大约99k次操作/秒,而现在的情况是说390k次操作/秒与另一个领先的140k次JSPerf测试(对我来说)相比。
http://jspef.com/merge-two-array-keeping-only-unique-values/26
这次我尽量减少数组交互,看起来我获得了一些性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | function findMerge(a1, a2) { var len1 = a1.length; for (var x = 0; x < a2.length; x++) { var found = false; for (var y = 0; y < len1; y++) { if (a2[x] === a1[y]) { found = true; break; } } if(!found){ a1.push(a2.splice(x--, 1)[0]); } } return a1; } |
编辑:我对我的函数做了一些更改,与JSperf站点上的其他函数相比,性能非常好。
使用土灰
我发现@gijsjanb的答案很有用,但我的数组中包含了具有许多属性的对象,因此我必须使用其中一个属性来消除它们的重复。
这是我使用
1 2 3 4 5 6 7 | 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 }] |
作为第三个参数传递的函数有两个参数(两个元素),如果它们相等,它必须返回
如果要检查唯一对象,请在比较中使用json.stringify。
1 2 3 4 5 6 7 8 9 10 11 | function arrayUnique(array) { var a = array.concat(); for(var i=0; i<a.length; ++i) { for(var j=i+1; j<a.length; ++j) { if(JSON.stringify(a[i]) === JSON.stringify(a[j])) a.splice(j--, 1); } } return a; } |
使用reduce func进行审查的另一种方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 | function mergeDistinct(arResult, candidate){ if (-1 == arResult.indexOf(candidate)) { arResult.push(candidate); } return arResult; } var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var arMerge = []; arMerge = array1.reduce(mergeDistinct, arMerge); arMerge = array2.reduce(mergeDistinct, arMerge);//["Vijendra","Singh","Shakya"]; |
一条线解决方案,作为对Liranuna:
1 2 3 4 5 6 7 8 9 | let array1 = ["Vijendra","Singh"]; let array2 = ["Singh","Shakya"]; // Merges both arrays let array3 = array1.concat(array2); //REMOVE DUPLICATE let removeDuplicate = [...new Set(array3)]; console.log(removeDuplicate); |
1 2 3 4 | Array.prototype.union = function (other_array) { /* you can include a test to check whether other_array really is an array */ other_array.forEach(function(v) { if(this.indexOf(v) === -1) {this.push(v);}}, this); } |
模块化,通用
这可以通过组成两个基本功能来实现。
1 2 3 | const getUniqueMerge = (...arrs) => getUniqueArr(mergeArrs(...arrs)) const getUniqueArr = (array) => Array.from(new Set(array)) const mergeArrs = (...arrs) => [].concat(...arrs) |
它可以处理无限数组或值
1 2 | console.log(getUniqueMerge([1,2,3], [3, 4,"a"], ["a","b","c"],"c","d")) // [1, 2, 3, 4,"a","b","c","d"] |
您可以尝试以下操作:
1 2 3 | const union = (a, b) => Array.from(new Set([...a, ...b])); console.log(union(["neymar","messi"], ["ronaldo","neymar"])); |
我觉得这样做更快。
删除=A=>{
1 2 3 4 5 6 7 8 | for (let i = a.length - 1; i >= 0; i--) { for (let j = i-1; j >= 0; j--) { if (a[i] === a[j]) a.splice(j--, 1); } } return a; |
}
如果您纯粹使用underline.js,那么它没有unionwith和unionby
您可以尝试:
用法:https://gist.github.com/samad-aghaei/7250ffb74ed80732deb1cb14d2bfb0
1 2 3 4 5 6 7 8 9 | var _uniqueMerge = function(opts, _ref){ for(var key in _ref) if (_ref && _ref[key] && _ref[key].constructor && _ref[key].constructor === Object) _ref[key] = _uniqueMerge((opts ? opts[key] : null), _ref[key] ); else if(opts && opts.hasOwnProperty(key)) _ref[key] = opts[key]; else _ref[key] = _ref[key][1]; return _ref; } |
以下是我的解决方案:https://gist.github.com/4692150,深度相等,易于使用结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function merge_arrays(arr1,arr2) { ... return {first:firstPart,common:commonString,second:secondPart,full:finalString}; } console.log(merge_arrays( [ [1,"10:55"] , [2,"10:55"] , [3,"10:55"] ],[ [3,"10:55"] , [4,"10:55"] , [5,"10:55"] ]).second); result: [ [4,"10:55"] , [5,"10:55"] ] |
之前写的原因相同(适用于任意数量的数组):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /** * 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; } |
最好也是最简单的方法是使用javascript的函数"some()",该函数返回true或false,指示数组是否包含对象的元素。你可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = array1; array2.forEach(function(elementArray2){ var isEquals = array1.some(function(elementArray1){ return elementArray1 === elementArray2; }) if(!isEquals){ array3.push(elementArray2); } }); console.log(array3); |
结果:
1 | ["Vijendra","Singh","Shakya"] |
你希望…没有复制…
如果像我一样,您需要支持较旧的浏览器,这适用于IE6+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function es3Merge(a, b) { var hash = {}, i = (a = a.slice(0)).length, e; while (i--) { hash[a[i]] = 1; } for (i = 0; i < b.length; i++) { hash[e = b[i]] || a.push(e); } return a; }; |
http://jspef.com/merge-two-array-keeping-only-unique-values/22
1 2 3 4 5 6 | Array.prototype.pushUnique = function(values) { for (var i=0; i < values.length; i++) if (this.indexOf(values[i]) == -1) this.push(values[i]); }; |
尝试:
1 2 3 4 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; array1.pushUnique(array2); alert(array1.toString()); // Output: Vijendra,Singh,Shakya |
这很快,可以对任意数量的数组进行排序,并且可以同时使用数字和字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function collate(a){ // Pass an array of arrays to collate into one array var h = { n: {}, s: {} }; for (var i=0; i < a.length; i++) for (var j=0; j < a[i].length; j++) (typeof a[i][j] ==="number" ? h.n[a[i][j]] = true : h.s[a[i][j]] = true); var b = Object.keys(h.n); for (var i=0; i< b.length; i++) b[i]=Number(b[i]); return b.concat(Object.keys(h.s)); } > a = [ [1,2,3], [3,4,5], [1,5,6], ["spoon","fork","5"] ] > collate( a ) [1, 2, 3, 4, 5, 6,"5","spoon","fork"] |
如果你不需要区分5和5,那么
1 2 3 4 5 6 7 8 9 10 | function collate(a){ var h = {}; for (i=0; i < a.length; i++) for (var j=0; j < a[i].length; j++) h[a[i][j]] = typeof a[i][j] ==="number"; for (i=0, b=Object.keys(h); i< b.length; i++) if (h[b[i]]) b[i]=Number(b[i]); return b; } [1, 2, 3, 4,"5", 6,"spoon","fork"] |
会的。
如果您不介意(或者更愿意)所有值都以字符串结尾,那么就这样:
1 2 3 4 5 6 7 8 | function collate(a){ var h = {}; for (var i=0; i < a.length; i++) for (var j=0; j < a[i].length; j++) h[a[i][j]] = true; return Object.keys(h) } ["1","2","3","4","5","6","spoon","fork"] |
如果您实际上不需要数组,但只想收集唯一值并对其进行迭代,那么(在大多数浏览器(和node.js)中):
1 2 3 4 | h = new Map(); for (i=0; i < a.length; i++) for (var j=0; j < a[i].length; j++) h.set(a[i][j]); |
也许更好。
我在尝试做同样的事情时遇到了这个帖子,但我想尝试一些不同的东西。我刚刚完成了下面的功能。我还有另一个变量"comparekeys"(键数组),用于进行浅对象比较。我以后可能会把它改成一个函数。
不管怎样,我没有包括那部分,因为它不适用于这个问题。我还把我的代码放到了JSPerf中。编辑:我修改了jspef中的条目。与140k相比,我的函数得到大约99k次操作/秒。
对于代码:我首先创建一个可用索引的数组,然后通过迭代第一个数组来消除它们。最后,我通过使用两个数组之间不匹配的经过修剪的索引数组来推进"剩余部分"。
http://jspef.com/merge-two-array-keeping-only-unique-values/26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function indiceMerge(a1, a2) { var ai = []; for (var x = 0; x < a2.length; x++) { ai.push(x) }; for (var x = 0; x < a1.length; x++) { for (var y = 0; y < ai.length; y++) { if (a1[x] === a2[ai[y]]) { ai.splice(y, 1); y--; } } } for (var x = 0; x < ai.length; x++) { a1.push(a2[ai[x]]); } return a1; } |
如果两个简单类型的排序数组没有重复项,这将在O(N)时间内合并它们,并且输出也将被排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function merge(a, b) { let i=0; let j=0; let c = []; for (;;) { if (i == a.length) { if (j == b.length) return c; c.push(b[j++]); } else if (j == b.length || a[i] < b[j]) { c.push(a[i++]); } else { if (a[i] == b[j]) ++i; // skip duplicates c.push(b[j++]); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /** * De-duplicate an array keeping only unique values. * Use hash table (js object) to filter-out duplicates. * The order of array elements is maintained. * This algorithm is particularly efficient for large arrays (linear time). */ function arrayUniqueFast(arr) { var seen = {}; var result = []; var i, len = arr.length; for (i = 0; i < len; i++) { var item = arr[i]; // hash table lookup if (!seen[item]) { result.push(item); seen[item] = true; } } return result; } ///// test var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var result = arrayUniqueFast(array1.concat(array2)); document.write('result: ' + result); |
有关对数组进行重复数据消除的其他方法,请参阅我的基准测试:https://jspef.com/de-duplicate-an-array-keeping-only-unique-values
1 2 | var a = [1,2,3] var b = [1,2,4,5] |
我喜欢一条衬里。这将把不同的b元素推到a
1 | b.forEach(item => a.includes(item) ? null : a.push(item)); |
以及另一个不会修改
1 2 | var c = a.slice(); b.forEach(item => c.includes(item) ? null : c.push(item)); |
对于大型输入,更好的选择是对数组进行排序。然后合并它们。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | function sortFunction(a, b) { return a - b; } arr1.sort(sortFunction); arr2.sort(sortFunction); function mergeDedup(arr1, arr2) { var i = 0, j = 0, result = []; while (i < arr1.length && j < arr2.length) { if (arr1[i] < arr2[j]) { writeIfNotSameAsBefore(result, arr1[i]); i++; } else if (arr1[i] > arr2[j]) { writeIfNotSameAsBefore(result, arr2[j]); j++; } else { writeIfNotSameAsBefore(result, arr1[i]); i++; j++; } } while (i < arr1.length) { writeIfNotSameAsBefore(result, arr1[i]); i++; } while (j < arr2.length) { writeIfNotSameAsBefore(result, arr2[j]); j++; } return result; } function writeIfNotSameAsBefore(arr, item) { if (arr[arr.length - 1] !== item) { arr[arr.length] = item; } return arr.length; } |
排序将采用o(nlogn+mlogm),其中n和m是数组的长度,o(x)用于合并,其中x=max(n,m);
1 2 3 | function set(a, b) { return a.concat(b).filter(function(x,i,c) { return c.indexOf(x) == i; }); } |
您可以使用loadash unionwith-
这个方法类似于联合,只是它接受比较器,比较器被调用来比较数组的元素。结果值是从出现该值的第一个数组中选择的。比较器由两个参数调用:(arrval,othval)。
1 2 3 4 5 | var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = _.unionWith(array1, array2, _.isEqual); console.log(array3); |
1 | <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"> |
用途:
1 2 3 4 5 | Array.prototype.merge = function (arr) { var key; for(key in arr) this[key] = arr[key]; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var arr1 = ["neymar","messi"] var arr2 = ["ronaldo","neymar"] var arr3 = [] var obj = {} for(var i = 0 ;i<arr1.length; i+=1){ if(!obj[arr1[i]]){ obj[arr1[i]] = true arr3.push(arr1[i]) } } for(var i = 0 ;i<arr2.length; i+=1){ if(!obj[arr2[i]]){ obj[arr2[i]] = true arr3.push(arr2[i]) } } console.log(arr3) |
可以合并结果并筛选重复项:
1 2 3 4 5 6 7 8 9 10 11 12 | let combinedItems = []; // items is an Array of arrays: [[1,2,3],[1,5,6],...] items.forEach(currItems => { if (currItems && currItems.length > 0) { combinedItems = combinedItems.concat(currItems); } }); let noDuplicateItems = combinedItems.filter((item, index) => { return !combinedItems.includes(item, index + 1); }); |
这是我在需要合并(或返回两个数组的并集)时使用的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var union = function (a, b) { for (var i = 0; i < b.length; i++) if (a.indexOf(b[i]) === -1) a.push(b[i]); return a; }; var a = [1, 2, 3, 'a', 'b', 'c']; var b = [2, 3, 4, 'b', 'c', 'd']; a = union(a, b); //> [1, 2, 3,"a","b","c", 4,"d"] var array1 = ["Vijendra","Singh"]; var array2 = ["Singh","Shakya"]; var array3 = union(array1, array2); //> ["Vijendra","Singh","Shakya"] |
取两个数组a和b
1 2 3 4 5 6 7 | var a = ['a','b','c']; var b = ['d','e','f']; var c = a.concat(b); //c is now an an array with: ['a','b','c','d','e','f'] |