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

Vij*_*dra 1256 javascript arrays merge

我有两个JavaScript数组:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
Run Code Online (Sandbox Code Playgroud)

我希望输出为:

var array3 = ["Vijendra","Singh","Shakya"];
Run Code Online (Sandbox Code Playgroud)

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

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

Lir*_*una 1554

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

ES5版本使用Array.concat:

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

console.log(array1.concat(array2));
Run Code Online (Sandbox Code Playgroud)

ES6版本使用解构

const array1 = ["Vijendra","Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = [...array1, ...array2];
Run Code Online (Sandbox Code Playgroud)

由于没有"内置"方法来删除重复项(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;
};
Run Code Online (Sandbox Code Playgroud)

然后,使用它:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
// Merges both arrays and gets unique items
var array3 = array1.concat(array2).unique(); 
Run Code Online (Sandbox Code Playgroud)

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

由于许多人对环形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 items
var array3 = arrayUnique(array1.concat(array2));
Run Code Online (Sandbox Code Playgroud)

对于那些有幸使用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;
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 注意,该算法是O(n ^ 2). (251认同)
  • OP接受了让他工作的第一个答案并且似乎签了字.我们仍在比较彼此的解决方案,发现修复错误,提高性能,确保其兼容性等等...... stackoverflow的美丽:-) (81认同)
  • 你应该总是在`hasOwnProperty`中使用`for ... in`,在这种情况下,原型方法很好 (16认同)
  • 设``[a,b,c]`和`[x,b,d]`是数组(假设引号).concat给出了'[a,b,c,x,b,d]`.unique()的输出不会是`[a,c,x,b,d]`.这并没有保留我认为的顺序 - 我相信OP想要`[a,b,c,x,d]` (6认同)
  • 我最初投了票,但改变了主意.将原型分配给Array.prototype具有打破"for ... in"语句的后果.因此,最好的解决方案可能是使用这样的函数,但不要将其指定为原型.有些人可能认为"for ... in"语句不应该用于迭代数组元素,但是人们经常以这种方式使用它们,所以至少这个解决方案应该谨慎使用. (6认同)
  • 只需按照另一个答案中所述使用Babel和Set()即可。 (2认同)

Gij*_*anB 580

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

console.log(_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]));
Run Code Online (Sandbox Code Playgroud)

http://underscorejs.org/#union

http://lodash.com/docs#union

  • 或者,甚至可能比下划线更好,API兼容[lodash](http://lodash.com/). (68认同)
  • 快速演绎lodash与最佳答案:http://jsperf.com/merge-two-arrays-keeping-only-unique-values (9认同)
  • @weaver _.flatten合并,但不会"删除重复". (8认同)
  • 我更喜欢underscore.js.我最终使用的是`underscore.flatten()`,它比union更好,因为它需要一个数组数组. (4认同)
  • @Ygg来自lodash docs."返回一个新的唯一值数组,**按顺序**,存在于一个或多个数组中." (3认同)

sim*_*imo 255

首先连接两个数组,然后只筛选出唯一的项.

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]
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/simo/98622/

编辑

正如@Dmitry所建议的那样(参见下面的第二条评论),一个性能更明智的解决方案是b在连接之前筛选出独特的项目a

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]
Run Code Online (Sandbox Code Playgroud)

  • @Andrew:更好:**1.**`var c = [... a,... b.filter(o =>!~a.indexOf(o))];`**2.**`var c = [... new Set([... a,... b])];`☺ (9认同)
  • 这里的原始解决方案具有删除每个源阵列中的欺骗的好处.我想这取决于您将使用的上下文. (4认同)

Adr*_*ria 173

这是使用扩展运算符和数组泛型的ECMAScript 6解决方案.

目前它只适用于Firefox,可能还适用于Internet Explorer Technical Preview.

但是如果你使用Babel,你现在可以拥有它.

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

console.log('output', mergeDedupe(input));
Run Code Online (Sandbox Code Playgroud)

  • 这应该添加到接受的答案中.这个解决方案比现在的解决方案更有效,更优雅,但这是我们不可避免的能够做到的(并且应该做到这一点). (13认同)
  • 可以使用`Array.from`代替spread运算符:`Array.from(new Set([].concat(... arr)))` (7认同)
  • 很难说这应该是接受的答案,因为问题是从2009年开始.但是,是的,这不仅更"高效"而且"优雅" (4认同)

Abd*_*UMI 162

ES6

array1.push(...array2) // => don't remove duplication 
Run Code Online (Sandbox Code Playgroud)

要么

[...array1,...array2] //   =>  don't remove duplication 
Run Code Online (Sandbox Code Playgroud)

要么

[...new Set([...array1 ,...array2])]; //   => remove duplication
Run Code Online (Sandbox Code Playgroud)

  • "Set"是去这里的方式 (11认同)
  • 第一个/第二个示例根本没有“union”+第一个示例炸毁了大型“Array”的堆栈+第三个示例非常慢并且消耗大量内存,因为必须构建两个中间“Array”+第三个示例example 只能用于编译时与已知数量的“Array”的“union”。 (3认同)
  • 不适用于对象数组,因为它只会合并对象引用,而不关心对象本身是否相等。 (3认同)
  • 请注意,对于set,无法对具有相同键值对的两个对象进行重复数据删除,除非它们是相同的对象引用. (2认同)

Ben*_*uer 64

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

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

  • @mwieczorek怎么样:`const array3 = [... new Set(array1.concat(array2))]` (8认同)
  • 我认为这是使用ES6的"已接受的答案". (6认同)
  • 如果您使用的是对象数组,则无法使用 (2认同)

sli*_*aid 36

这是一个稍微不同的循环.通过最新版Chrome中的一些优化,它是解决两个阵列联合的最快方法(Chrome 38.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);
  }
}
Run Code Online (Sandbox Code Playgroud)

while循环:~589k ops/s
过滤器:~445k ops/s
lodash:308k ops/s
for循环:225k ops/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 call
            array3.push(itm);
            assoc[itm] = null;
        }
    }

    return array3;
};
Run Code Online (Sandbox Code Playgroud)

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

这里的最佳答案是每个值(i-1)上的双循环仍然明显变慢.lodash仍然很强大,我仍然会推荐给那些不介意在他们的项目中添加库的人.对于那些不想要的人来说,我的while循环仍然是一个很好的答案,过滤器的答案在这里有很强的表现,在撰写本文时,最新的Canary Chrome(44.0.2360)测试结果一目了然.

看看Mike的回答Dan Stocker的回答,如果你想提高速度的话.在完成几乎所有可行的答案后,这些是迄今为止所有结果中最快的.


Raj*_*amy 35

你可以用ECMAScript 6简单地完成它,

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [...new Set([...array1 ,...array2])];
console.log(array3); // ["Vijendra", "Singh", "Shakya"];
Run Code Online (Sandbox Code Playgroud)
  • 使用spread运算符连接数组.
  • 使用Set创建一组不同的元素.
  • 再次使用spread运算符将Set转换为数组.

  • 如果由于某种原因你不想使用扩展运算符,那么还有:`Array.from(new Set(array1.concat(array2)))`. (3认同)
  • 我收到错误:类型'Set <string>'不是数组类型. (2认同)

Bab*_*med 35

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"]
Run Code Online (Sandbox Code Playgroud)

  • 并且不适用于对象数组 (3认同)

小智 21

合并两个数组并删除es6中的副本

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 ]
Run Code Online (Sandbox Code Playgroud)


akh*_*hid 21

基于ES6的联合解决方案

let arr1 = [1,2,3,4,5];
let arr2 = [3,4,5,6];
let result = [...new Set([...arr1, ...arr2])];
console.log(result);
Run Code Online (Sandbox Code Playgroud)

  • 它也与基于字符串的元素一起工作。做得好! (2认同)

GAg*_*new 18

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;
};
Run Code Online (Sandbox Code Playgroud)

一个更好的阵列合并功能.

  • `var test = ['a','b','c']; console.log(test);`将打印`["a","b","c",merge:function]` (4认同)
  • 不确定 indexOf() 方法的成本是多少,但这可能是最快的 ES5 兼容方法。同样值得一提的是不需要可变长度的参数。这种方法是可链接的。@slickplaid 加载库从来都不是“如何在 javascript 中执行”问题的答案。肯定很多图书馆都有一个功能来完成这 7 行工作。 (2认同)

Dan*_*ker 18

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

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 这真是太神奇了,特别是如果你正在做弦乐.数字需要一个额外的步骤来保持它们.如果您在完成后不介意(或关心)所有内容都是字符串,那么此功能可以很好地击败所有其他选项.不错的工作.绩效结果如下:http://jsperf.com/merge-two-arrays-keeping-only-unique-values/21 (2认同)

Pit*_*uli 18

编辑:

只有当项目很少时,第一种解决方案才是最快的。当超过 400 个项目时,Set解决方案成为最快的。并且当有 100,000 个项目时,它比第一个解决方案快了一千倍。

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

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


基于 jsperf,将两个数组合并为一个新数组的最快方法(编辑:如果少于 400 个项目)如下:

for (var i = 0; i < array2.length; i++)
    if (array1.indexOf(array2[i]) === -1)
      array1.push(array2[i]);
Run Code Online (Sandbox Code Playgroud)

这个慢了 17%:

array2.forEach(v => array1.includes(v) ? null : array1.push(v));
Run Code Online (Sandbox Code Playgroud)

这个慢了 45% (编辑:当少于 100 个项目时。当有很多项目时会快很多)

var a = [...new Set([...array1 ,...array2])];
Run Code Online (Sandbox Code Playgroud)

并且接受的答案要慢 55%(并且要写更长的时间)(编辑:当有 100 000 个项目时,它比任何其他方法慢几个数量级)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

https://jsperf.com/merge-2-arrays-without-duplicate


小智 17

只要投入我的两分钱.

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;
}
Run Code Online (Sandbox Code Playgroud)

这是我经常使用的一种方法,它使用一个对象作为hashlookup表来进行重复检查.假设散列是O(1),那么这在O(n)中运行,其中n是a.length + b.length.老实说,我不知道浏览器如何处理哈希,但它在数千个数据点上表现良好.


Nic*_*ack 14

你为什么不用一个物体?看起来你正试图模拟一套.但是,这不会保留订单.

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
}
Run Code Online (Sandbox Code Playgroud)

  • 我为什么这么说?该条件的目的是忽略对象原型中可能存在的属性. (2认同)

Kam*_*ski 14

表现

今天 2020.10.15 我在 Chrome v86、Safari v13.1.2 和 Firefox v81 上针对所选解决方案在 MacOs HighSierra 10.13.6 上执行测试。

结果

适用于所有浏览器

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

在此处输入图片说明

细节

我执行 2 个测试用例:

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

关于解决方案 ABCDEGHJLM 在下面的片段中提出

// https://stackoverflow.com/a/10499519/860099
function A(arr1,arr2) {
  return _.union(arr1,arr2)
}

// https://stackoverflow.com/a/53149853/860099
function B(arr1,arr2) {
  return _.unionWith(arr1, arr2, _.isEqual);
}

// https://stackoverflow.com/a/27664971/860099
function C(arr1,arr2) {
  return [...new Set([...arr1,...arr2])]
}

// https://stackoverflow.com/a/48130841/860099
function D(arr1,arr2) {
  return Array.from(new Set(arr1.concat(arr2)))
}

// https://stackoverflow.com/a/23080662/860099
function E(arr1,arr2) {
  return arr1.concat(arr2.filter((item) => arr1.indexOf(item) < 0))
}


// https://stackoverflow.com/a/28631880/860099
function 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/860099
function 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/860099
function 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/860099
function 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 call
            array3.push(itm);
            assoc[itm] = null;
        }
    }

    return array3;
}

// https://stackoverflow.com/a/39336712/860099
function 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])}]`);
})
Run Code Online (Sandbox Code Playgroud)
<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!
Run Code Online (Sandbox Code Playgroud)

这是 chrome 的示例测试运行

在此处输入图片说明

更新

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


Sta*_*avm 13

我知道这个问题与对象数组无关,但搜索者确实会在这里结束。

因此值得为未来的读者添加一种适当的 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} ]
Run Code Online (Sandbox Code Playgroud)


Zig*_*612 11

最好的解决方案......

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

没有重复

a = [1, 2, 3];
b = [3, 2, 1, "prince"];

a.concat(b.filter(function(el) {
    return a.indexOf(el) === -1;
}));
Run Code Online (Sandbox Code Playgroud)

有副本

["prince", "asish", 5].concat(["ravi", 4])
Run Code Online (Sandbox Code Playgroud)

如果您想要没有重复,您可以从这里尝试更好的解决方案 - 喊叫代码.

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

试试Chrome浏览器控制台

 f12 > console
Run Code Online (Sandbox Code Playgroud)

输出:

["prince", "asish", 5, "ravi", 4]

[1, 2, 3, "prince"]
Run Code Online (Sandbox Code Playgroud)


Tus*_*ade 11

  • 实现此目的的现代方法是简单地使用散布运算符
  • 为了避免重复,我们可以有效地使用Sets默认情况下,集合不允许重复
  • 为了从Set获得作为数组的输出,我们可以使用Array.from()

因此,这是您的情况的演示-

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var resArr = Array.from(new Set([...array1, ...array2]));
console.log(resArr);
Run Code Online (Sandbox Code Playgroud)


Top*_*pW3 11

合并两个数组有很多解决方案。它们可以分为两大类(除了使用 lodash 或 underscore.js 等 3rd 方库)。

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

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

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

结合

// mutable operation(array1 is the combined array)
array1.push(...array2);
array1.unshift(...array2);

// immutable operation
const combined = array1.concat(array2);
const combined = [...array1, ...array2];    // ES6
Run Code Online (Sandbox Code Playgroud)

统一

统一数组的方法有很多,我个人推荐以下两种方法。

// a little bit tricky
const merged = combined.filter((item, index) => combined.indexOf(item) === index);
const merged = [...new Set(combined)];
Run Code Online (Sandbox Code Playgroud)

在组合它们之前过滤掉项目

还有很多方法,但我个人建议下面的代码,因为它很简单。

const merged = array1.concat(array2.filter(secItem => !array1.includes(secItem)));
Run Code Online (Sandbox Code Playgroud)


And*_*rew 10

简化了simo的答案并将其变成了一个很好的功能.

function mergeUnique(arr1, arr2){
    return arr1.concat(arr2.filter(function (item) {
        return arr1.indexOf(item) === -1;
    }));
}
Run Code Online (Sandbox Code Playgroud)

  • 我相信这比接受的答案要干净得多。此外,看起来 ECMAScript 5.1 + 支持过滤器,现在非常受支持。 (3认同)
  • 一行: `const mergeUnique = (a, b) =&gt; a.concat(b.filter(v =&gt; a.indexOf(v) === -1))` (3认同)
  • 这不会从 arr1 中删除重复项,它只会添加 arr2 中的唯一元素 (3认同)

rnw*_*ser 10

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

[...new Set([...array1 ,...array2])]
Run Code Online (Sandbox Code Playgroud)


Her*_* Qu 9

我的一分半便士:

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);
Run Code Online (Sandbox Code Playgroud)


Moh*_*med 8

你可以使用Underscore.js's => uniq来实现它:

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

console.log(array3)
Run Code Online (Sandbox Code Playgroud)

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


Jar*_*red 7

const array3 = array1.filter(t=> !array2.includes(t)).concat(array2)
Run Code Online (Sandbox Code Playgroud)

  • 请阅读[如何写出一个好的答案?](https://stackoverflow.com/help/how-to-answer)。虽然此代码块可能会回答OP的问题,但如果您解释此代码与问题中的代码有何不同,您更改了什么,为什么更改它以及为什么解决问题,那么这个答案会更有用无需介绍其他人。 (2认同)
  • 对我来说似乎是一个很好的答案。我很高兴这个世界不存在太多我懒得去学的规则 (2认同)

med*_*iev 6

新解决方案(使用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 )
};
Run Code Online (Sandbox Code Playgroud)

用法:

>>> ['Vijendra', 'Singh'].uniqueMerge(['Singh', 'Shakya'])
["Vijendra", "Singh", "Shakya"]
Run Code Online (Sandbox Code Playgroud)

Array.prototype.indexOf(用于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;
  };
Run Code Online (Sandbox Code Playgroud)


Ama*_*osh 6

//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
  }
Run Code Online (Sandbox Code Playgroud)

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

  • IE6不支持Array.prototype.indexOf,只需粘贴Mozilla给出的支持方法,这样IE就不会抛出错误. (4认同)

Kar*_*gla 6

它可以使用Set完成.

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);
Run Code Online (Sandbox Code Playgroud)
<div style="width:100%;height:4rem;line-height:4rem;background-color:steelblue;color:#DDD;text-align:center;font-family:Calibri" > 
  temp text 
</div>
Run Code Online (Sandbox Code Playgroud)


use*_*877 6

对于ES6,只需一行:

a = [1, 2, 3, 4]
b = [4, 5]
[...new Set(a.concat(b))]  // [1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)


Laj*_*ros 5

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]
Run Code Online (Sandbox Code Playgroud)


小智 5

ES2015 的函数式方法

遵循union两个Arrays的函数方法 a只是concatand的组合filter。为了提供最佳性能,我们求助于本机Set数据类型,它针对属性查找进行了优化。

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

Array A      + Array B

[unique]     + [unique]
[duplicated] + [unique]
[unique]     + [duplicated]
[duplicated] + [duplicated]
Run Code Online (Sandbox Code Playgroud)

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


Array A      + Array B

[unique]     + [unique]
[duplicated] + [unique]
[unique]     + [duplicated]
[duplicated] + [duplicated]
Run Code Online (Sandbox Code Playgroud)

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

// 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) );
Run Code Online (Sandbox Code Playgroud)

事实证明unionn它只是foldl(又名Array.prototype.reduce),它union作为它的减速器。注意:由于该实现不使用额外的累加器,因此在不带参数的情况下应用它时会抛出错误。


Dev*_*vWL 5

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

使用 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);
}
Run Code Online (Sandbox Code Playgroud)

使用示例代码笔

// 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]
Run Code Online (Sandbox Code Playgroud)


can*_*ero 5

array1.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos)
Run Code Online (Sandbox Code Playgroud)

关于这个的好处是性能,你通常在使用数组时会链接像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
Run Code Online (Sandbox Code Playgroud)

(我不喜欢污染Array.prototype,这将是尊重链的唯一方式 - 定义一个新函数会破坏它 - 所以我认为像这样的东西是唯一的方法来完成它)