如何在JavaScript中合并两个数组并删除重复项

我有两个JavaScript数组:

var array1 = ["Vijendra","Singh"];var array2 = ["Singh", "Shakya"];

我希望输出是:

var array3 = ["Vijendra","Singh","Shakya"];

输出数组应该删除重复的单词。

如何在JavaScript中合并两个数组,以便我仅从每个数组中以与它们插入原始数组相同的顺序获取唯一项?

1875517 次浏览

新的解决方案(使用Array.prototype.indexOfArray.prototype.concat):

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 )};

用法:

>>> ['Vijendra', 'Singh'].uniqueMerge(['Singh', 'Shakya'])["Vijendra", "Singh", "Shakya"]

Array.prototype.index(对于Internet Explorer):

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;};

合并数组(不删除重复项)

ES5版本使用Array.concat

var array1 = ["Vijendra", "Singh"];var array2 = ["Singh", "Shakya"];
array1 = array1.concat(array2);
console.log(array1);

ES6版本使用解构

const array1 = ["Vijendra","Singh"];const array2 = ["Singh", "Shakya"];const array3 = [...array1, ...array2];

由于没有“内置”的方式来删除重复项(ECMA-262实际上有Array.forEach,这对于此非常有用),我们必须手动执行:

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;};

然后,使用它:

var array1 = ["Vijendra","Singh"];var array2 = ["Singh", "Shakya"];// Merges both arrays and gets unique itemsvar array3 = array1.concat(array2).unique();

这也将保留数组的顺序(即,不需要排序)。

由于许多人对Array.prototypefor in循环的原型增强感到恼火,这里有一种侵入性较小的使用方法:

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 itemsvar array3 = arrayUnique(array1.concat(array2));

对于那些有幸使用ES5可用的浏览器的人,您可以像这样使用Object.defineProperty

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;}});
//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}

其他浏览器的indexOf方法的实现取自MDC

你为什么不使用一个对象呢?看起来你正在尝试模拟一个集合。然而,这不会保持顺序。

var set1 = {"Vijendra":true, "Singh":true}var set2 = {"Singh":true,  "Shakya":true}
// Merge second object into firstfunction merge(set1, set2){for (var key in set2){if (set2.hasOwnProperty(key))set1[key] = set2[key]}return set1}
merge(set1, set2)
// Create set from arrayfunction setify(array){var result = {}for (var item in array){if (array.hasOwnProperty(item))result[array[item]] = true}return result}
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;};

一个更好的数组合并函数。

在Dojo 1.6+

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);});

更新

请参阅工作代码。

使用Underscore.js或Lo-Dash,您可以:

console.log(_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

http://underscorejs.org/#union

http://lodash.com/docs#union

只是扔在我的两分钱。

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.老实说,我不知道浏览器是如何进行哈希的,但它在数千个数据点上表现良好。

取两个数组a和b

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']

这是我的解决方案https://gist.github.com/4692150,具有深度相等和易于使用的结果:

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"]]
Array.prototype.add = function(b){var a = this.concat();                // clone current objectif(!b.push || !b.length) return a;    // if b is not an array, or empty, then return a unchangedif(!a.length) return b.concat();      // if original is empty, return b
// go through all the elements of bfor(var i = 0; i < b.length; i++){// if b's value is not in a, then add itif(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]

用途:

Array.prototype.merge = function (arr) {var key;for(key in arr)this[key] = arr[key];};

出于同样的原因(适用于任何数量的数组):

/*** 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; }

合并无限数量的数组或非数组并保持其唯一:

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]

首先连接两个数组,接下来只过滤掉唯一的项目:

var a = [1, 2, 3], b = [101, 2, 1, 10]var c = a.concat(b)var d = c.filter((item, pos) => c.indexOf(item) === pos)
console.log(d) // d is [1, 2, 3, 101, 10]

编辑

正如建议的那样,更具性能智慧的解决方案是在与a连接之前过滤掉b中的唯一项:

var a = [1, 2, 3], b = [101, 2, 1, 10]var c = a.concat(b.filter((item) => a.indexOf(item) < 0))
console.log(c) // c is [1, 2, 3, 101, 10]

这是我在需要合并(或返回两个数组的并集)时使用的函数。

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"]
function set(a, b) {return a.concat(b).filter(function(x,i,c) { return c.indexOf(x) == i; });}

就计算时间而言,这是最有效的一个。它还保持元素的初始顺序。

首先过滤第二个数组中的所有重复项,然后将剩下的连接到第一个数组。

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]

这是它的略微改进(更快)版本,有一个缺点,数组不能错过值:

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];}

这是对循环的略有不同的看法。通过最新版本的Chrome中的一些优化,它是解析两个数组合并的最快方法(Chrome38.0.2111)。

http://jsperf.com/merge-two-arrays-keeping-only-unique-values

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);}}

同时循环:~589kops/s
filter:~445kops/s
Lodash:308kops/s
循环:225kops/s

一条评论指出,我的一个设置变量导致我的循环领先于其他变量,因为它不必初始化一个空数组来写入。我同意这一点,所以我重写了测试以平衡竞争环境,并包括一个更快的选项。

http://jsperf.com/merge-two-arrays-keeping-only-unique-values/52

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 callarray3.push(itm);assoc[itm] = null;}}
return array3;};

在这个替代解决方案中,我结合了一个答案的关联数组解决方案,以消除循环中的.indexOf()调用,这在第二个循环中减慢了很多速度,并包含了其他用户在他们的答案中建议的一些其他优化。

这里的最高答案是每个值(i-1)都有双循环,仍然显着慢。洛达什仍然表现强劲,我仍然会推荐给任何不介意向他们的项目添加库的人。对于那些不想的人来说,我的而循环仍然是一个很好的答案,过滤器答案在这里表现得非常出色,在撰写本文时,最新的金丝雀Chrome(44.0.2360)击败了我的所有测试。

如果你想加快速度,可以看看迈克的回答Dan Stocker的回答。在经历了几乎所有可行的答案后,这些是迄今为止所有结果中最快的。

这很简单,可以用jQuery在一行中完成:

var arr1 = ['Vijendra', 'Singh'], arr2 =['Singh', 'Shakya'];
$.unique(arr1.concat(arr2))//one line
["Vijendra", "Singh", "Shakya"]

这是一个使用点差算子和数组泛型的ECMAScript 6解决方案。

目前它仅适用于Firefox,可能还适用于Internet Explorer技术预览版。

但是如果你使用巴别塔,你现在可以拥有它。

const input = [[1, 2, 3],[101, 2, 1, 10],[2, 1]];const mergeDedupe = (arr) => {return [...new Set([].concat(...arr))];}
console.log('output', mergeDedupe(input));

只需避开嵌套循环(O(n^2))和.indexOf()(+O(n))。

function merge(a, b) {var hash = {};var 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);}
var array1 = ["Vijendra", "Singh"];var array2 = ["Singh", "Shakya"];
var array3 = merge(array1, array2);
console.log(array3);

Array.prototype.pushUnique = function(values){for (var i=0; i < values.length; i++)if (this.indexOf(values[i]) == -1)this.push(values[i]);};

尝试:

var array1 = ["Vijendra","Singh"];var array2 = ["Singh", "Shakya"];array1.pushUnique(array2);alert(array1.toString());  // Output: Vijendra,Singh,Shakya

这里有一个简单的例子:

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"]));

我们定义unique(array)来删除冗余元素,并使用concat函数来组合两个数组。

如果像我一样,你需要支持较旧的浏览器,这适用于IE6+

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;};

我在尝试做同样的事情时遇到了这篇文章,但我想尝试不同的东西。我只是组成了下面的函数。我还有另一个变量,'compareKeys',(键数组)用于进行浅层对象比较。我可能会在将来将其更改为函数。

不管怎样,我没有包括那部分,因为它不适用于这个问题。我还把我的代码放入了四处传播的jspef中。编辑:我修复了我在jspef中的条目。与140k相比,我的函数获得大约99k操作/秒。

代码:我首先制作一个可用索引的数组,然后通过迭代第一个数组来消除它们。最后,我通过使用两个数组之间不匹配的向下修剪的索引数组来推入“剩余”。

http://jsperf.com/merge-two-arrays-keeping-only-unique-values/26

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;}

这是我的第二个答案,但我相信最快?我希望有人帮我检查并在评论中回复。

我的第一次尝试大约99kops/sec,这个循环是说390kops/sec vs140k的另一个领先的jspef测试(对我来说)。

这一次,我试图尽可能地减少数组交互,看起来我获得了一些性能。

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;}

编辑:我对我的函数做了一些更改,与jspef站点上的其他函数相比,性能非常好。

我的一个半便士:

Array.prototype.concat_n_dedupe = function(other_array) {return this.concat(other_array) // add second.reduce(function(uniques, item) { // dedupe allif (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);

假设原始数组不需要重复数据删除,这应该很快,保留原始顺序,并且不会修改原始数组…

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;}

用法:

var array1 = ["Vijendra","Singh"];var array2 = ["Singh", "Shakya"];var array3 = arrayMerge(array1, array2);
console.log(array3);//-> [ 'Vijendra', 'Singh', 'Shakya' ]

这很快,可以整理任意数量的数组,并同时处理数字和字符串。

function collate(a){ // Pass an array of arrays to collate into one arrayvar 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”,那么

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"]

会做。

如果你不介意(或者更喜欢)所有值都以字符串结尾,那么就这样:

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)中):

h = new Map();for (i=0; i < a.length; i++)for (var j=0; j < a[i].length; j++)h.set(a[i][j]);

这可能更可取。

最好的解决方案…

您可以通过点击直接在浏览器控制台中检查…

无重复

a = [1, 2, 3];b = [3, 2, 1, "prince"];
a.concat(b.filter(function(el) {return a.indexOf(el) === -1;}));

与重复

["prince", "asish", 5].concat(["ravi", 4])

如果你想要没有重复,你可以从这里尝试一个更好的解决方案-大喊代码

[1, 2, 3].concat([3, 2, 1, "prince"].filter(function(el) {return [1, 2, 3].indexOf(el) === -1;}));

试试Chrome浏览器控制台

 f12 > console

输出:

["prince", "asish", 5, "ravi", 4]
[1, 2, 3, "prince"]

您可以简单地使用ECMAScript 6来完成它,

var array1 = ["Vijendra", "Singh"];var array2 = ["Singh", "Shakya"];var array3 = [...new Set([...array1 ,...array2])];console.log(array3); // ["Vijendra", "Singh", "Shakya"];
  • 使用点差算子连接数组。
  • 使用设置创建一组不同的元素。
  • 再次使用扩展运算符将Set转换为数组。

看起来公认的答案是我的测试中最慢的;

注意我正在通过合并2个对象数组

<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>JS Bin</title></head><body><button type='button' onclick='doit()'>do it</button><script>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);}}}}</script></body></html>

const merge(...args)=>(new Set([].concat(...args)))

[...array1,...array2] //   =>  don't remove duplication

[...new Set([...array1 ,...array2])]; //   => remove duplication

大输入的更好选择是对数组进行排序。然后合并它们。

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(nlo爱人+mlogm),其中n和m是数组的长度,O(x)用于合并,其中x=Max(n, m);

ES2015的功能方法

按照函数式方法,两个Array中的union只是concatfilter的组合。为了提供最佳性能,我们采用了本机Set数据类型,该数据类型针对属性查找进行了优化。

无论如何,与union函数相关的关键问题是如何处理重复项。以下排列是可能的:

Array A      + Array B
[unique]     + [unique][duplicated] + [unique][unique]     + [duplicated][duplicated] + [duplicated]

前两个排列很容易用一个函数处理。然而,后两个更复杂,因为只要你依赖Set查找就无法处理它们。由于切换到普通的旧Object属性查找会导致严重的性能下降,下面的实现只是忽略了第三和第四个排列。你必须构建一个单独的union版本来支持它们。


// 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) );

从这里开始,实现一个unionn函数变得微不足道,它接受任意数量的数组(灵感来自naomik的评论):

// 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) );

原来unionn只是foldl(也就是Array.prototype.reduce),它将union作为它的减速器。注意:由于实现不使用额外的累加器,因此当您在没有参数的情况下应用它时,它会抛出错误。

最简单的方法是使用concat()合并数组,然后使用filter()删除重复项,或者使用concat()然后将合并的数组放入Set()中。

第一种方式:

const firstArray = [1,2, 2];const secondArray = [3,4];// now lets merge themconst mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4]//now use filter to remove dupsconst removeDuplicates = mergedArray.filter((elem, index) =>  mergedArray.indexOf(elem) === index); // [1,2,3, 4]

第二种方式(但对UI有性能影响):

const firstArray = [1,2, 2];const secondArray = [3,4];// now lets merge themconst mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4]const removeDuplicates = new Set(mergedArray);
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,您可以合并两个数组而不会获得重复项。在我的示例中,我在对象上使用了一个给定的字段,但可能只是对象本身。

使用Reduce Func进行审查的另一种方法:

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"];

您可以简单地使用Underscore.js's=>uniq来实现它:

array3 = _.uniq(array1.concat(array2))
console.log(array3)

它将打印["Vijendra","Singh","Shakya"]

用法:https://gist.github.com/samad-aghaei/7250ffb74ed80732debb1cbb14d2bfb0

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;}

如果要检查唯一对象,请在比较中使用JSON.stringify。

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;}

最好和最简单的方法是使用JavaScript的函数“一些()”,该函数返回true或false,指示数组是否包含对象的元素。你可以这样做:

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);

结果:

["Vijendra", "Singh", "Shakya"]

你希望…不要复制它…

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);}

我简化了这个答案的优点并将其变成了一个不错的函数:

function mergeUnique(arr1, arr2){return arr1.concat(arr2.filter(function (item) {return arr1.indexOf(item) === -1;}));}

一行解决方案作为LiraNuna的后续:

let array1 = ["Vijendra","Singh"];let array2 = ["Singh", "Shakya"];
// Merges both arrayslet array3 = array1.concat(array2);
//REMOVE DUPLICATElet removeDuplicate = [...new Set(array3)];console.log(removeDuplicate);

您可以合并结果并过滤重复项:

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);});

使用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

/*** 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 lookupif (!seen[item]) {result.push(item);seen[item] = true;}}return result;}
///// testvar array1 = ["Vijendra", "Singh"];var array2 = ["Singh", "Shakya"];
var result = arrayUniqueFast(array1.concat(array2));document.write('<br>result: ' + result);

对于其他方法去重数组,请参阅我的基准测试:https://jsperf.com/de-duplicate-an-array-keeping-only-unique-values

为了它……这里有一个单行解决方案:

const x = [...new Set([['C', 'B'],['B', 'A']].reduce( (a, e) => a.concat(e), []))].sort()// ['A', 'B', 'C']

不是特别可读,但它可以帮助某人:

  1. 将初始累加器值设置为空数组的duce函数应用。
  2. Reduce函数使用concat将每个子数组附加到累加器数组上。
  3. 这样做的结果作为构造函数参数传递,以创建一个新的Set
  4. 扩展运算符用于将Set转换为数组。
  5. sort()函数应用于新数组。

使用设置(ECMAScript 2015),它将如此简单:

const array1 = ["Vijendra", "Singh"];const array2 = ["Singh", "Shakya"];console.log(Array.from(new Set(array1.concat(array2))));

我学到了一个厚颜无耻的小方法,用扩展运算符连接两个数组:

var array1 = ['tom', 'dick', 'harry'];var array2 = ['martin', 'ricky'];
array1.push(...array2);

“…”扩展运算符将以下数组拆分为单独的项,然后ush可以将它们作为单独的参数处理。

它可以使用Set来完成。

var array1 = ["Vijendra","Singh"];var array2 = ["Singh", "Shakya"];
var array3 = array1.concat(array2);var tempSet = new Set(array3);array3 = Array.from(tempSet);
//show outputdocument.body.querySelector("div").innerHTML = JSON.stringify(array3);
<div style="width:100%;height:4rem;line-height:4rem;background-color:steelblue;color:#DDD;text-align:center;font-family:Calibri" >temp text</div>

var a = [1,2,3]var b = [1,2,4,5]

我喜欢单行。这将把不同的b元素推到a

b.forEach(item => a.includes(item) ? null : a.push(item));

另一个版本不会修改

var c = a.slice();b.forEach(item => c.includes(item) ? null : c.push(item));

去重复单个或合并和去重复多个数组输入。下面的示例。

使用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 valuesarr.map((value) => { // map adds each value to Set objectset.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);}

使用示例CODEPEN

// SCENARIOlet 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'];
// USEAGElet uniqueArrayAll = arrayDeDuplicate(a, b, c, d, e);let uniqueArraySingle = arrayDeDuplicate(b);
// OUTPUTconsole.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]
array1.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos)

这个的好处是性能,一般来说,当使用数组时,你会链接像filter,map等方法,所以你可以添加该行,它会用array1合并和删除重复的array2,而不需要引用后面的方法(当你链接你没有的方法时),例如:

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,这是尊重链条的唯一方法——定义一个新函数会破坏它——所以我认为这样的事情是实现这一目标的唯一方法)

对于ES6,只有一行:

a = [1, 2, 3, 4]b = [4, 5][...new Set(a.concat(b))]  // [1, 2, 3, 4, 5]
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]

您可以使用loadash unionWith-_.unionWith([arrays], [comparator])

此方法类似于_. Union,只是它接受用于比较数组元素的比较器。结果值从出现该值的第一个数组中选择。使用两个参数调用比较器:(arrVal, othVal)。

var array1 = ["Vijendra","Singh"];var array2 = ["Singh", "Shakya"]; 
var array3 = _.unionWith(array1, array2, _.isEqual);console.log(array3);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

如果您不想要特定属性的副本(例如ID)

let noDuplicate = array1.filter ( i => array2.findIndex(a => i.id==a.id)==-1 );let result = [...noDuplicate, ...array2];

如果你纯粹使用underscore.js,它没有unionWith, unionBy

你可以试试:_.uniq(_.union(arr1, arr2), (obj) => obj.key)(key是每个对象的key参数)这应该有助于在两个数组合并后获得唯一。

给定两个没有重复项的简单类型的排序数组,这将在O(n)时间内合并它们,并且输出也将被排序。

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 duplicatesc.push(b[j++]);}}}

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));

你可以试试这个:

const union = (a, b) => Array.from(new Set([...a, ...b]));
console.log(union(["neymar","messi"], ["ronaldo","neymar"]));

带过滤器的最简单解决方案:

var array1 = ["Vijendra","Singh"];var array2 = ["Singh", "Shakya"];
var mergedArrayWithoutDuplicates = array1.concat(array2.filter(seccondArrayItem => !array1.includes(seccondArrayItem)));

模块化,通用

这可以通过组合两个基本功能来实现。

const getUniqueMerge = (...arrs) => getUniqueArr(mergeArrs(...arrs))const getUniqueArr = (array) => Array.from(new Set(array))const mergeArrs = (...arrs) => [].concat(...arrs)

它可以处理无限的数组或值

console.log(getUniqueMerge(["Vijendra","Singh"],["Singh", "Shakya"])// ["Vijendra", "Singh", "Shakya"]
console.log(getUniqueMerge(["Sheldon", "Cooper"], ["and", "Cooper", "Amy", "and"], "Farrah", "Amy", "Fowler"))// ["Sheldon", "Cooper", "and", "Amy", "Farrah", "Fowler"]

我认为这工作得更快。

removeDup = a => {
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;}

ES2019

你可以像union(array1, array2, array3, ...)一样使用它

/*** Merges two or more arrays keeping unique items. This method does* not change the existing arrays, but instead returns a new array.*/function union<T>(...arrays: T[]) {return [...new Set([...arrays].flat())];}

它是ES2019的,因为flat()函数,但你可以使用core-js将其作为一个多边形填充。这里的T是TypeScript泛型类型,如果你不使用TypeScript,你可以删除它。如果你使用的是TypeScript,请确保将"lib": ["es2019.array"]添加到tsconfig.json中的编译器选项中。

或者…

只需要使用_

减少它们!!!

这个替代方案不是显式合并和消重,而是采用一个数组并用另一个数组减少它,以便第一个数组的每个值都可以在累积行为中迭代和解构,通过利用数组的持久性来忽略已经包含的值,因为递归性。

array2.reduce(reducer, array1.reduce(reducer, []))

测试示例:

var array1 = ["Vijendra","Singh","Singh"];var array2 = ["Singh", "Shakya", "Shakya"];const reducer = (accumulator, currentValue) => accumulator.includes(currentValue) ? accumulator : [...accumulator, currentValue];
console.log(array2.reduce(reducer, array1.reduce(reducer, [])));
// a reduce on first array is needed to ensure a deduplicated array used as initial value on the second array being reduced

结论

当无聊的for-each方法想要避免时(并不是说它没有用),它会更加优雅和有用。

处理消重的concat()限制。

不需要像Underscore.js、JQuery或Lo-Dash这样的外部库,也不需要创建任何内置函数来实现所需的合并和消重效果。

哦,嘿!,它可以作为一行完成!!!


这要归功于ES5(ECMAScript 2015),美丽的#1和华丽的#2

   //1.merge two array into one array
var arr1 = [0, 1, 2, 4];var arr2 = [4, 5, 6];
//for merge array we use "Array.concat"
let combineArray = arr1.concat(arr2); //output
alert(combineArray); //now out put is 0,1,2,4,4,5,6 but 4 reapeat
//2.same thing with "Spread Syntex"
let spreadArray = [...arr1, ...arr2];
alert(spreadArray);  //now out put is 0,1,2,4,4,5,6 but 4 reapete

/*if we need remove duplicate element method use are1.Using set2.using .filter3.using .reduce*/

合并两个数组有很多解决方案。它们可以分为两大类(除了使用第三方库,如Lodash或underscore.js)。

a)合并两个数组并删除重复的项目。

b)在组合之前过滤掉项目。

合并两个数组并删除重复项

结合

// mutable operation(array1 is the combined array)array1.push(...array2);array1.unshift(...array2);
// immutable operationconst combined = array1.concat(array2);const combined = [...array1, ...array2];    // ES6

统一

统一数组的方法有很多,我个人建议下面两种方法。

// a little bit trickyconst merged = combined.filter((item, index) => combined.indexOf(item) === index);const merged = [...new Set(combined)];

在组合之前过滤掉项目

也有很多方法,但由于其简单性,我个人建议使用下面的代码。

const merged = array1.concat(array2.filter(secItem => !array1.includes(secItem)));

我知道这个问题不是关于物体的数组,但搜索者确实在这里结束。

因此,值得为未来的读者添加一种适当的ES6合并方式,然后删除重复项

对象数组

var arr1 = [ {a: 1}, {a: 2}, {a: 3} ];var arr2 = [ {a: 1}, {a: 2}, {a: 4} ];
var arr3 = arr1.concat(arr2.filter( ({a}) => !arr1.find(f => f.a == a) ));
// [ {a: 1}, {a: 2}, {a: 3}, {a: 4} ]

编辑:

只有在物品很少的情况下,第一个解决方案才是最快的。当物品超过400件时,Set的解决方案变得最快。当有100,000件时,它比第一个解决方案快一千倍。

考虑到性能只有在有很多项目时才重要,并且Set解决方案是迄今为止最具可读性的,因此在大多数情况下它应该是正确的解决方案

下面的perf结果是用少量项目计算的


基于jspef,将两个数组合并为一个新数组的最快方法(编辑:如果少于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

如果您合并对象数组,请考虑使用洛达什UnionBy函数,它允许您设置自定义谓词比较对象:

import { unionBy } from 'lodash';
const a = [{a: 1, b: 2}];const b = [{a: 1, b: 3}];const c = [{a: 2, b: 4}];
const result = UnionBy(a,b,c, x => x.a);

结果是:[{ a: 1; b: 2 }, { a: 2; b: 4 }]

数组中第一次传递的匹配用于结果

这是具有对象数组的对象的选项:

const a = [{param1: "1", param2: 1},{param1: "2", param2: 2},{param1: "4", param2: 4}]const b = [{param1: "1", param2: 1},{param1: "4", param2: 5}]

var result = a.concat(b.filter(item =>!JSON.stringify(a).includes(JSON.stringify(item))));
console.log(result);//Result [{param1: "1", param2: 1},{param1: "2", param2: 2},{param1: "4", param2: 4},{param1: "4", param2: 5}]

性能

今天2020.10.15我在Chromev86,Safariv13.1.2和Firefox v81上对MacO HighSierra 10.13.6进行测试以获取所选解决方案。

搜索结果

对于所有浏览器

  • 解决方案H快/最快
  • 解决方案L很快
  • 解决方案D在chrome上对于大数组最快
  • 解决方案G在小数组上很快
  • 解M对于小数组最慢
  • 解决方案E对于大型阵列最慢

在此处输入图片描述

详情

我执行两个测试用例:

  • 对于2个元素数组-您可以运行它这里
  • 对于10000个元素数组-您可以运行它这里

解决方案一个BCDEgHJLM出现在下面的片段

// https://stackoverflow.com/a/10499519/860099function A(arr1,arr2) {return _.union(arr1,arr2)}
// https://stackoverflow.com/a/53149853/860099function B(arr1,arr2) {return _.unionWith(arr1, arr2, _.isEqual);}
// https://stackoverflow.com/a/27664971/860099function C(arr1,arr2) {return [...new Set([...arr1,...arr2])]}
// https://stackoverflow.com/a/48130841/860099function D(arr1,arr2) {return Array.from(new Set(arr1.concat(arr2)))}
// https://stackoverflow.com/a/23080662/860099function E(arr1,arr2) {return arr1.concat(arr2.filter((item) => arr1.indexOf(item) < 0))}

// https://stackoverflow.com/a/28631880/860099function G(arr1,arr2) {var hash = {};var i;  
for (i = 0; i < arr1.length; i++) {hash[arr1[i]] = true;}for (i = 0; i < arr2.length; i++) {hash[arr2[i]] = true;}return Object.keys(hash);}
// https://stackoverflow.com/a/13847481/860099function H(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;}


// https://stackoverflow.com/a/1584377/860099function J(arr1,arr2) {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;}
return arrayUnique(arr1.concat(arr2));}

// https://stackoverflow.com/a/25120770/860099function L(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 callarray3.push(itm);assoc[itm] = null;}}
return array3;}
// https://stackoverflow.com/a/39336712/860099function M(arr1,arr2) {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));
const dedupe = comp(afrom) (createSet);
const union = xs => ys => {const zs = createSet(xs);return concat(xs) (filter(x => zs.has(x)? false: zs.add(x)) (ys));}
return union(dedupe(arr1)) (arr2)}


// -------------// TEST// -------------
var array1 = ["Vijendra","Singh"];var array2 = ["Singh", "Shakya"];
[A,B,C,D,E,G,H,J,L,M].forEach(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==" crossorigin="anonymous"></script>  
This snippet only presents functions used in performance tests - it not perform tests itself!

这里是Chrome的示例测试运行

在此处输入图片描述

更新

我删除了案例F、I、K,因为它们修改了输入数组,并且基准测试给出了错误的结果

对于n个数组,您可以像这样获得并集。

function union(arrays) {return new Set(arrays.flat()).keys();};

构建了一个测试器来检查一些面向性能的答案有多快。请随时添加更多。到目前为止,Set既是最简单也是最快的选项(随着记录数量的增加,边距更大),至少对于简单的Number类型。

const records = 10000, //max records per arraymax_int = 100, //max integer value per arraydup_rate = .5; //rate of duplicationlet perf = {}, //performance logger,ts = 0,te = 0,array1 = [], //init arraysarray2 = [],array1b = [],array2b = [],a = [];
//populate randomized arraysfor (let i = 0; i < records; i++) {let r = Math.random(),n = r * max_int;if (Math.random() < .5) {array1.push(n);r < dup_rate && array2.push(n);} else {array2.push(n);r < dup_rate && array1.push(n);}}//simple deep copies short of rfdc, in case someone wants to test with more complex data typesarray1b = JSON.parse(JSON.stringify(array1));array2b = JSON.parse(JSON.stringify(array2));console.log('Records in Array 1:', array1.length, array1b.length);console.log('Records in Array 2:', array2.length, array2b.length);
//test method 1 (jsperf per @Pitouli)ts = performance.now();for (let i = 0; i < array2.length; i++)if (array1.indexOf(array2[i]) === -1)array1.push(array2[i]); //modifies array1te = performance.now();perf.m1 = te - ts;console.log('Method 1 merged', array1.length, 'records in:', perf.m1);array1 = JSON.parse(JSON.stringify(array1b)); //reset array1
//test method 2 (classic forEach)ts = performance.now();array2.forEach(v => array1.includes(v) ? null : array1.push(v)); //modifies array1te = performance.now();perf.m2 = te - ts;console.log('Method 2 merged', array1.length, 'records in:', perf.m2);
//test method 3 (Simplest native option)ts = performance.now();a = [...new Set([...array1, ...array2])]; //does not modify source arrayste = performance.now();perf.m3 = te - ts;console.log('Method 3 merged', a.length, 'records in:', perf.m3);
//test method 4 (Selected Answer)ts = performance.now();a = array1.concat(array2); //does not modify source arraysfor (let i = 0; i < a.length; ++i) {for (let j = i + 1; j < a.length; ++j) {if (a[i] === a[j])a.splice(j--, 1);}}te = performance.now();perf.m4 = te - ts;console.log('Method 4 merged', a.length, 'records in:', perf.m4);
//test method 5 (@Kamil Kielczewski)ts = performance.now();
function K(arr1, arr2) {let r = [],h = {};
while (arr1.length) {let e = arr1.shift(); //modifies array1if (!h[e]) h[e] = 1 && r.push(e);}
while (arr2.length) {let e = arr2.shift(); //modifies array2if (!h[e]) h[e] = 1 && r.push(e);}
return r;}a = K(array1, array2);te = performance.now();perf.m5 = te - ts;console.log('Method 5 merged', a.length, 'records in:', perf.m4);array1 = JSON.parse(JSON.stringify(array1b)); //reset array1array2 = JSON.parse(JSON.stringify(array2b)); //reset array2

for (let i = 1; i < 6; i++) {console.log('Method:', i, 'speed is', (perf['m' + i] / perf.m1 * 100).toFixed(2), '% of Method 1');}

这是另一个使用Set的简洁解决方案:

const o1 = {a: 1};const arr1 = ['!@#$%^&*()', 'gh', 123, o1, 1, true, undefined, null];const arr2 = ['!@#$%^&*()', 123, 'abc', o1, 0x001, true, void 0, 0];
const mergeUnique = (...args) => [ ...new Set([].concat(...args)) ];
console.log(mergeUnique(arr1, arr2));

关注效率,又想在线做

const s = new Set(array1);array2.forEach(a => s.add(a));const merged_array = [...s]; // optional: convert back in array type

ES6提供了一个单行解决方案,通过使用解构和设置来合并多个数组而不重复。

const array1 = ['a','b','c'];const array2 = ['c','c','d','e'];const array3 = [...new Set([...array1,...array2])];console.log(array3); // ["a", "b", "c", "d", "e"]

为了提供更简单,更优雅的东西,在这个时代,使用现有的库:

import {pipe, concat, distinct} from 'iter-ops';
// our inputs:const array1 = ['Vijendra', 'Singh'];const array2 = ['Singh', 'Shakya'];
const i = pipe(array1,concat(array2), // adding arraydistinct() // making it unique);
console.log([...i]); //=> ['Vijendra', 'Singh', 'Shakya']

它既是高性能的,因为我们只迭代一次,而且代码非常容易阅读。

如果你有非常大的列表,这不是用于合并,因为已经记录了许多解决方案,但我用这个解决方案解决了我的问题(因为大多数数组过滤解决方案适用于简单数组)

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;});

我有一个类似的请求,但它是数组中元素的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"]

ES 6版本

试试这个这个应该能解决你的问题

var array1=["Vijendra","Singh"];var array2=["Singh","Shakya"];

var输出=[… new Set([… array1,… array2])]

console.log('合并数组',输出)

  1. 使用array.concat()array.filter()
  2. 使用新的Set对象传播运算符
  3. 使用array.concat新Set对象

let array1 = [1, 2, 3, 4, 5]let array2 = [1, 4, 6, 9]
// Using array.concat and array.filterconst array3 = array1.concat(array2.filter((item)=> array1.indexOf(item) == -1 ))console.log('array3 : ', array3);
// Using new Set and Spread Operatorconst array4 = [...new Set([...array1 ,...array2])];console.log('array4 : ', array4);
// Using array.concat and new Setconst array5 = [...new Set(array1.concat(array2))];console.log('array5 : ', array5);

您可以使用new Set来删除重复

[...new Set([...array1 ,...array2])]
const array3 = array1.filter(t=> !array2.includes(t)).concat(array2)