获取javascript数组中的所有唯一值(删除重复项)

Get all unique values in a JavaScript array (remove duplicates)

我有一组数字需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它工作得很好,直到数组中有一个零为止。我在这找到了另一个脚本,所以看起来几乎和它一模一样,但它没有失败。

所以为了帮助我学习,有人能帮我确定原型脚本哪里出错了吗?

1
2
3
4
5
6
Array.prototype.getUnique = function() {
 var o = {}, a = [], i, e;
 for (i = 0; e = this[i]; i++) {o[e] = 1};
 for (e in o) {a.push (e)};
 return a;
}

重复问题的更多答案:

  • 从javascript数组中删除重复项

类似问题:

  • 获取数组中出现一次以上(即:不唯一)的所有值


使用javascript 1.6/ecmascript 5,可以使用数组的本机filter方法,方法如下,以获得具有唯一值的数组:

1
2
3
4
5
6
7
function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

本机方法filter将在数组中循环,只留下那些通过给定回调函数onlyUnique的条目。

如果给定值是第一个发生的,则onlyUnique检查。如果没有,它必须是一个副本,并且不会被复制。

此解决方案不需要任何额外的库(如jquery或prototype.js)即可工作。

它也适用于混合值类型的数组。

对于不支持本机方法filterindexOf的旧浏览器(

如果要保留最后一次出现的值,只需将indexOf替换为lastIndexOf

使用ES6,可以缩短为:

1
2
3
4
5
// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((v, i, a) => a.indexOf(v) === i);

// unique is ['a', 1, 2, '1']

感谢卡米洛马丁的评论提示。

ES6有一个本地对象Set来存储唯一的值。要获取具有唯一值的数组,现在可以执行以下操作:

1
2
3
4
5
var myArray = ['a', 1, 'a', 2, '1'];

let unique = [...new Set(myArray)];

// unique is ['a', 1, 2, '1']

Set的构造器接受一个类似数组的不可重复对象,展开运算符...将集合转换回数组。感谢Lukas Liese在评论中的提示。


更新了ES6/ES2015的答案:使用该集合,单线解决方案是:

1
2
var items = [4,5,4,6,3,4,5,2,23,1,4,4,4]
var uniqueItems = Array.from(new Set(items))

哪些回报

1
[4, 5, 6, 3, 2, 23, 1]

正如Le_m所建议的,这也可以使用spread操作符来缩短,比如

1
var uniqueItems = [...new Set(items)]


您还可以使用underline.js。

1
console.log(_.uniq([1, 2, 1, 3, 1, 4]));
1
<script src="http://underscorejs.org/underscore-min.js">

将返回:

1
[1, 2, 3, 4]


我知道这个问题已经有30多个答案了。但我先通读了所有现有的答案,并做了自己的研究。

我将所有答案分为4个可能的解决方案:

  • 使用新的ES6功能:[...new Set( [1, 1, 2] )];
  • 使用对象{ }防止重复
  • 使用辅助数组[ ]
  • 使用filter + indexOf
  • 以下是答案中的示例代码:

    使用新的ES6功能:[...new Set( [1, 1, 2] )];

    1
    2
    3
    4
    function uniqueArray0(array) {
      var result = Array.from(new Set(array));
      return result    
    }

    使用对象{ }防止重复

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function uniqueArray1( ar ) {
      var j = {};

      ar.forEach( function(v) {
        j[v+ '::' + typeof v] = v;
      });

      return Object.keys(j).map(function(v){
        return j[v];
      });
    }

    使用辅助数组[ ]

    1
    2
    3
    4
    5
    6
    7
    function uniqueArray2(arr) {
        var a = [];
        for (var i=0, l=arr.length; i<l; i++)
            if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
                a.push(arr[i]);
        return a;
    }

    使用filter + indexOf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function uniqueArray3(a) {
      function onlyUnique(value, index, self) {
          return self.indexOf(value) === index;
      }

      // usage
      var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

      return unique;
    }

    我想知道哪一个更快。我已经制作了谷歌表单样本来测试函数。注意:ECMA 6在谷歌表单中不可用,所以我无法测试它。

    测试结果如下:enter image description here

    我希望看到使用对象{ }的代码会赢,因为它使用哈希。所以我很高兴测试在Chrome和IE中显示了这个算法的最佳结果。感谢@rab提供的代码。


    一行,纯javascript

    用ES6语法

    list = list.filter((x, i, a) => a.indexOf(x) == i)

    1
    2
    3
    x --> item in array
    i --> index of item
    a --> array reference, (in this case"list")

    enter image description here

    用ES5语法

    1
    2
    3
    list = list.filter(function (x, i, a) {
        return a.indexOf(x) == i;
    });

    浏览器兼容性:IE9+


    从那以后,我发现了一个使用jquery的好方法

    1
    2
    3
    arr = $.grep(arr, function(v, k){
        return $.inArray(v ,arr) === k;
    });

    注意:这段代码是从保罗·爱尔兰的"打鸭子"帖子中提取出来的-我忘了评分:P


    ES6最短解:[...new Set( [1, 1, 2] )];

    或者,如果要修改数组原型(如原始问题):

    1
    2
    3
    Array.prototype.getUnique = function() {
        return [...new Set( [this] )];
    };

    ECMAScript 6目前(2015年8月)仅在现代浏览器中部分实现,但Babel已经非常流行,将ES6(甚至ES7)重新发布到ES5。这样,您就可以在今天编写ES6代码了!

    如果你想知道...是什么意思,它被称为spread operator。从MDN:?spread运算符允许在需要多个参数(用于函数调用)或多个元素(用于数组文本)的位置扩展表达式?。因为集合是可iterable(并且只能有唯一的值),所以spread运算符将展开集合以填充数组。

    学习ES6的资源:

    • Axel Rauschmayer博士研究ES6
    • 从JS周报中搜索"ES6"
    • 来自Mozilla Hacks博客的ES6深度文章


    最简单的解决方案:

    1
    2
    var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
    console.log([...new Set(arr)]);

    或:

    1
    2
    var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
    console.log(Array.from(new Set(arr)));


    最简单、最快(铬合金)的方法:

    1
    2
    3
    4
    5
    6
    7
    Array.prototype.unique = function() {
        var a = [];
        for (var i=0, l=this.length; i<l; i++)
            if (a.indexOf(this[i]) === -1)
                a.push(this[i]);
        return a;
    }

    只需遍历数组中的每个项,测试该项是否已经在列表中,如果没有,则推送到返回的数组。

    根据JSPerf的说法,这个函数是我在任何地方都能找到的最快的函数——尽管可以随意添加自己的函数。

    非原型版本:

    1
    2
    3
    4
    5
    6
    7
    function uniques(arr) {
        var a = [];
        for (var i=0, l=arr.length; i<l; i++)
            if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
                a.push(arr[i]);
        return a;
    }

    分选

    当还需要对数组进行排序时,以下是最快的:

    1
    2
    3
    4
    5
    6
    7
    8
    Array.prototype.sortUnique = function() {
        this.sort();
        var last_i;
        for (var i=0;i<this.length;i++)
            if ((last_i = this.lastIndexOf(this[i])) !== i)
                this.splice(i+1, last_i-i);
        return this;
    }

    或非原型:

    1
    2
    3
    4
    5
    6
    7
    8
    function sortUnique(arr) {
        arr.sort();
        var last_i;
        for (var i=0;i<arr.length;i++)
            if ((last_i = arr.lastIndexOf(arr[i])) !== i)
                arr.splice(i+1, last_i-i);
        return arr;
    }

    在大多数非Chrome浏览器中,这也比上面的方法快。


    仅限表演!此代码可能比此处所有代码快10倍*适用于所有浏览器,并且内存影响最小…更多

    如果不需要重用旧数组,那么在将其转换为唯一数组之前,顺便做一些必要的其他操作,这可能是最快的方法,也非常短。

    1
    var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];

    那你可以试试这个

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];

    function toUnique(a, b, c) { //array,placeholder,placeholder
      b = a.length;
      while (c = --b)
        while (c--) a[b] !== a[c] || a.splice(c, 1);
      return a // not needed ;)
    }
    console.log(toUnique(array));
    //[3, 4, 5, 6, 7, 8, 9, 0, 2, 1]

    我在阅读这篇文章时想到了这个函数…

    Fast Algorithm To Find Unique Items in JavaScript Array

    我不喜欢for循环。它有很多参数,我喜欢while循环。在所有浏览器中,除了我们都非常喜欢的浏览器外,它是最快的循环…铬。

    总之,我编写了第一个使用while的函数。是的,它比本文中找到的函数快一点,但还不够。

    下一步使用现代JS.Object.keys我用js1.7的object.keys替换了另一个for循环…稍微快一点,再短一点(铬合金比铬合金快两倍);)。不够!unique3()

    在这一点上,我在思考我的独特功能到底需要什么。我不需要旧的数组,我想要一个快速函数。所以我用了2个while循环+拼接.unique4()

    没必要说我印象深刻。

    Chrome:通常每秒150000次操作跃升到每秒1800000次操作。

    即:80000次/秒vs 3500000次/秒

    iOS:18000 op/s对170000 op/s

    游猎:80000次/秒vs 6000000次/秒

    证明http://jspef.com/wgu或更好地使用console.time…微时间…无论什么

    unique5()只是为了向您展示如果您想要保留旧数组会发生什么。

    如果你不知道自己在做什么,就不要使用Array.prototype。我只是抄了很多过去。如果要创建本机原型,请使用Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})。示例:https://stackoverflow.com/a/20463021/2450730

    演示http://jsfiddle.net/46s7g/

    注意:在执行此操作后,旧数组将被销毁/成为唯一数组。

    如果你不能阅读上面的代码,请阅读一本javascript书,或者这里有一些关于较短代码的解释。https://stackoverflow.com/a/21353032/2450730

    有些人正在使用indexOf…不要。。。http://jspef.com/dgfgghfghfghfghgfghfghfghfghfhgfh

    对于空数组

    1
    !array.length||toUnique(array);


    这里的许多答案可能对初学者没有用处。如果一个数组的重复数据消除很困难,他们真的知道原型链,甚至jquery吗?

    在现代浏览器中,一个干净而简单的解决方案是将数据存储在一个集合中,该集合被设计为一个唯一值列表。

    1
    2
    const cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
    const uniqueCars = Array.from(new Set(cars));

    Array.from对于将集合转换回数组非常有用,这样您就可以轻松访问数组所具有的所有出色的方法(特性)。同样的事情也有其他的方法。但是您可能根本不需要Array.from,因为集合有很多有用的特性,比如foreach。

    如果您需要支持旧的Internet Explorer,因而不能使用set,那么一种简单的技术是将项目复制到新的数组中,同时预先检查它们是否已经在新的数组中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // Create a list of cars, with duplicates.
    var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
    // Create a list of unique cars, to put a car in if we haven't already.
    var uniqueCars = [];

    // Go through each car, one at a time.
    cars.forEach(function (car) {
        // The code within the following block runs only if the
        // current car does NOT exist in the uniqueCars list
        // - a.k.a. prevent duplicates
        if (uniqueCars.indexOf(car) === -1) {
            // Since we now know we haven't seen this car before,
            // copy it to the end of the uniqueCars list.
            uniqueCars.push(car);
        }
    });

    为了使这个可以立即重用,让我们把它放到一个函数中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function deduplicate(data) {
        if (data.length > 0) {
            var result = [];

            data.forEach(function (elem) {
                if (result.indexOf(elem) === -1) {
                    result.push(elem);
                }
            });

            return result;
        }
    }

    为了消除重复,我们现在就这么做。

    1
    var uniqueCars = deduplicate(cars);

    当函数完成时,deduplicate(cars)部分成为我们命名的result。

    把你喜欢的数组的名字传给它。


    1
    2
    3
    4
    5
    6
    7
    ["Defects","Total","Days","City","Defects"].reduce(function(prev, cur) {
      return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
     }, []);

    [0,1,2,0,3,2,1,5].reduce(function(prev, cur) {
      return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
     }, []);


    这个原型getUnique不是完全正确的,因为如果我有一个类似的数组:["1",1,2,3,4,1,"foo"],它将返回["1","2","3","4"]"1"是字符串,1是整数,它们是不同的。

    以下是正确的解决方案:

    1
    2
    3
    Array.prototype.unique = function(a){
        return function(){ return this.filter(a) }
    }(function(a,b,c){ return c.indexOf(a,b+1) < 0 });

    使用:

    1
    2
    3
    var foo;
    foo = ["1",1,2,3,4,1,"foo"];
    foo.unique();

    以上将产生["1",2,3,4,1,"foo"]


    我们可以使用ES6设置:

    1
    2
    3
    4
    var duplicatedArray = [1, 2, 3, 4, 5, 1, 1, 1, 2, 3, 4];
    var uniqueArray = Array.from(new Set(duplicatedArray));

    console.log(uniqueArray);

    //输出将为

    1
    uniqueArray = [1,2,3,4,5];


    如果不扩展array.prototype(据说这是一个糟糕的实践)或使用jquery/underline,您可以简单地对数组执行filter

    通过保留最后一个事件:

    1
    2
    3
    4
    5
    6
        function arrayLastUnique(array) {
            return array.filter(function (a, b, c) {
                // keeps last occurrence
                return c.indexOf(a, b + 1) < 0;
            });
        },

    或第一次出现:

    1
    2
    3
    4
    5
    6
        function arrayFirstUnique(array) {
            return array.filter(function (a, b, c) {
                // keeps first occurrence
                return c.indexOf(a) === b;
            });
        },

    好吧,它只是JavaScriptECMAScript 5+,这意味着只有IE9+,但它很适合在原生HTML/JS(Windows应用商店应用程序、Firefox OS、Sencha、PhoneGap、Titanium…)中进行开发。


    这是因为0在javascript中是一个错误的值。

    如果数组的值为0或任何其他错误值,则this[i]将是错误的。


    如果您使用的是原型框架,则无需执行"for"循环,您可以使用http://www.prototypejs.org/api/array/uniq,如下所示:

    1
    var a = Array.uniq();

    它将生成一个没有重复项的重复数组。我发现你的问题是在寻找一种方法来计算不同的数组记录,所以

    uniq()

    我用过

    size()

    这是我的简单结果。对不起,如果我打错了什么

    编辑:如果要转义未定义的记录,可以添加

    compact()

    之前,像这样:

    1
    var a = Array.compact().uniq();


    1
    2
    3
    4
    5
    6
    Array.prototype.getUnique = function() {
        var o = {}, a = []
        for (var i = 0; i < this.length; i++) o[this[i]] = 1
        for (var e in o) a.push(e)
        return a
    }


    魔术

    1
    a.filter(e=>!(t[e]=e in t))

    o(n)性能;我们假设您的数组在at={}中。这里解释(+jeppe impr.)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var a1 = [5,6,0,4,9,2,3,5,0,3,4,1,5,4,9];
    var a2 = [[2, 17], [2, 17], [2, 17], [1, 12], [5, 9], [1, 12], [6, 2], [1, 12]];
    var a3 = ['Mike', 'Adam','Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'];

    let t={}, nd = a => a.filter(e=>!(t[e]=e in t));

    //"stand-alone" version working with global t:
    // a1.filter((t={},e=>!(t[e]=e in t)));

    // print
    let c= x => console.log(JSON.stringify(x));            
    c( nd(a1) );
    c( nd(a2) );
    c( nd(a3) );


    奇怪的是,以前没有人建议过……要在数组中按对象键(下面的id键)删除重复项,可以执行以下操作:

    1
    2
    3
    const uniqArray = array.filter((obj, idx, arr) => (
      arr.findIndex((o) => o.id === obj.id) === idx
    ))

    我不知道为什么加布里埃尔·席尔维拉这样写这个函数,但是一个简单的形式,对我来说也同样有效,没有缩小是:

    1
    2
    3
    4
    5
    Array.prototype.unique = function() {
      return this.filter(function(value, index, array) {
        return array.indexOf(value, index + 1) < 0;
      });
    };

    或在咖啡中描述:

    1
    2
    3
    4
    Array.prototype.unique = ->
      this.filter( (value, index, array) ->
        array.indexOf(value, index + 1) < 0
      )

    在简单方法中查找唯一数组值

    1
    2
    3
    4
    5
    6
    7
    8
    function arrUnique(a){
      var t = [];
      for(var x = 0; x < a.length; x++){
        if(t.indexOf(a[x]) == -1)t.push(a[x]);
      }
      return t;
    }
    arrUnique([1,4,2,7,1,5,9,2,4,7,2]) // [1, 4, 2, 7, 5, 9]

    相反地,要解决这个问题,在加载数组时没有重复的内容可能会很有用,set对象可以这样做,但在所有浏览器中都不可用。它节省了内存,如果您需要多次查看其内容,它会更高效。

    1
    2
    3
    4
    5
    Array.prototype.add = function (elem) {
       if (this.indexOf(elem) == -1) {
          this.push(elem);
       }
    }

    Sample:

    1
    2
    set = [];
    [1,3,4,1,2,1,3,3,4,1].forEach(function(x) { set.add(x); });

    给你的是set = [1,3,4,2]


    来自Shamasis Bhattacharya的博客(o(2n)time complexity):

    1
    2
    3
    4
    5
    6
    Array.prototype.unique = function() {
        var o = {}, i, l = this.length, r = [];
        for(i=0; i<l;i+=1) o[this[i]] = this[i];
        for(i in o) r.push(o[i]);
        return r;
    };

    来自Paul Irish的博客:jquery .unique()的改进:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    (function($){

        var _old = $.unique;

        $.unique = function(arr){

            // do the default behavior only if we got an array of elements
            if (!!arr[0].nodeType){
                return _old.apply(this,arguments);
            } else {
                // reduce the array to contain no dupes via grep/inArray
                return $.grep(arr,function(v,k){
                    return $.inArray(v,arr) === k;
                });
            }
        };
    })(jQuery);

    // in use..
    var arr = ['first',7,true,2,7,true,'last','last'];
    $.unique(arr); // ["first", 7, true, 2,"last"]

    var arr = [1,2,3,4,5,4,3,2,1];
    $.unique(arr); // [1, 2, 3, 4, 5]


    基于ES6的解决方案…

    1
    2
    3
    var arr = [2, 3, 4, 2, 3, 4, 2];
    const result = [...new Set(arr)];
    console.log(result);


    我有一个稍微不同的问题,我需要从数组中删除具有重复ID属性的对象。这是有效的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    let objArr = [{
      id: '123'
    }, {
      id: '123'
    }, {
      id: '456'
    }];

    objArr = objArr.reduce((acc, cur) => [
      ...acc.filter((obj) => obj.id !== cur.id), cur
    ], []);

    console.log(objArr);


    如果您对额外的依赖关系还满意,或者您的代码库中已经有了一个库,那么您可以使用lodash(或下划线)从一个数组中删除重复项。

    用法

    如果您的代码库中没有它,请使用NPM安装它:

    1
    npm install lodash

    然后如下使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import _ from 'lodash';
    let idArray = _.uniq ([
        1,
        2,
        3,
        3,
        3
    ]);
    console.dir(idArray);

    出:

    1
    [ 1, 2, 3 ]

    您也可以使用sugar.js:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [1,2,2,3,1].unique() // => [1,2,3]

    [{id:5, name:"Jay
    <hr><P>我发现序列化散列键有助于我为对象工作。</P>[cc lang="
    javascript"]Array.prototype.getUnique = function() {
            var hash = {}, result = [], key;
            for ( var i = 0, l = this.length; i < l; ++i ) {
                key = JSON.stringify(this[i]);
                if ( !hash.hasOwnProperty(key) ) {
                    hash[key] = true;
                    result.push(this[i]);
                }
            }
            return result;
        }

    如果有人使用击倒式JS

    1
    ko.utils.arrayGetDistinctValues()

    顺便说一下,我们已经了解了所有的ko.utils.array*实用程序。


    这行得通。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function getUnique(a) {
      var b = [a[0]], i, j, tmp;
      for (i = 1; i < a.length; i++) {
        tmp = 1;
        for (j = 0; j < b.length; j++) {
          if (a[i] == b[j]) {
            tmp = 0;
            break;
          }
        }
        if (tmp) {
          b.push(a[i]);
        }
      }
      return b;
    }

    Building on other answers, here's another variant that takes an optional flag to choose a strategy (keep first occurrence or keep last):

    Without extending Array.prototype

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function unique(arr, keepLast) {
      return arr.filter(function (value, index, array) {
        return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
      });
    };

    // Usage
    unique(['a', 1, 2, '1', 1, 3, 2, 6]); // -> ['a', 1, 2, '1', 3, 6]
    unique(['a', 1, 2, '1', 1, 3, 2, 6], true); // -> ['a', '1', 1, 3, 2, 6]

    扩展Array.prototype

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Array.prototype.unique = function (keepLast) {
      return this.filter(function (value, index, array) {
        return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
      });
    };

    // Usage
    ['a', 1, 2, '1', 1, 3, 2, 6].unique(); // -> ['a', 1, 2, '1', 3, 6]
    ['a', 1, 2, '1', 1, 3, 2, 6].unique(true); // -> ['a', '1', 1, 3, 2, 6]


    看看这个。jquery提供uniq方法:https://api.jquery.com/jquery.unique/唯一/

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var ids_array = []

    $.each($(my_elements), function(index, el) {
        var id = $(this).attr("id")
        ids_array.push(id)
    });

    var clean_ids_array = jQuery.unique(ids_array)

    $.each(clean_ids_array, function(index, id) {
       elment = $("#" + id)   // my uniq element
       // TODO WITH MY ELEMENT
    });


    使用对象键创建唯一数组,我尝试了以下操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function uniqueArray( ar ) {
      var j = {};

      ar.forEach( function(v) {
        j[v+ '::' + typeof v] = v;
      });


      return Object.keys(j).map(function(v){
        return j[v];
      });
    }  

    uniqueArray(["1",1,2,3,4,1,"foo", false, false, null,1]);

    返回["1", 1, 2, 3, 4,"foo", false, null]


    也可以使用jquery

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var a = [1,5,1,6,4,5,2,5,4,3,1,2,6,6,3,3,2,4];

    // note: jQuery's filter params are opposite of javascript's native implementation :(
    var unique = $.makeArray($(a).filter(function(i,itm){
        // note: 'index', not 'indexOf'
        return i == $(a).index(itm);
    }));

    // unique: [1, 5, 6, 4, 2, 3]

    最初的答案是:jquery函数从数组中获取所有唯一元素?


    使用lodash和identity lambda函数,只需在使用对象之前定义它。

    1
    2
    3
    4
    const _ = require('lodash');
    ...    
    _.uniqBy([{a:1,b:2},{a:1,b:2},{a:1,b:3}], v=>v.a.toString()+v.b.toString())
    _.uniq([1,2,3,3,'a','a','x'])

    并将有:

    1
    2
    [{a:1,b:2},{a:1,b:3}]
    [1,2,3,'a','x']

    (这是最简单的方法)


    如果您有强大的reduce方法(&ge;5.1),您可以尝试如下操作:

    1
    2
    3
    4
    5
    Array.prototype.uniq = function() {
      return this.reduce(function(sofar, cur) {
        return sofar.indexOf(cur) < 0 ? sofar.concat([cur]) : sofar;
      }, []);
    };

    这不是最有效的实现(因为indexOf检查,在最坏的情况下可能会检查整个列表)。如果效率很重要,您可以保留某些随机访问结构(例如,{}中出现的"历史记录",并键入这些记录。这基本上就是最有投票权的答案所能做的,所以举个例子来看看。


    这个不是纯的,它会修改数组,但这是最快的。如果你的速度更快,请写在评论中;)

    http://jspef.com/unique-array-wedbeb

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    Array.prototype.uniq = function(){
        for(var i = 0, l = this.length; i < l; ++i){
            var item = this[i];
            var duplicateIdx = this.indexOf(item, i + 1);
            while(duplicateIdx != -1) {
                this.splice(duplicateIdx, 1);
                duplicateIdx = this.indexOf(item, duplicateIdx);
                l--;
            }
        }

        return this;
    }

    [
    "",2,4,"A","abc",
    "",2,4,"A","abc",
    "",2,4,"A","abc",
    "",2,4,"A","abc",
    "",2,4,"A","abc",
    "",2,4,"A","abc",
    "",2,4,"A","abc",
    "",2,4,"A","abc"
    ].uniq() //  ["",2,4,"A","abc"]


    接受选择器的版本应该非常快速和简洁:

    1
    2
    3
    4
    5
    6
    7
    function unique(xs, f) {
      var seen = {};
      return xs.filter(function(x) {
        var fx = (f && f(x)) || x;
        return !seen[fx] && (seen[fx] = 1);
      });
    }

    对我来说,当您说唯一值时,这意味着值在数据集中只出现一次。

    下面过滤值数组,检查给定值的第一个和最后一个索引是否相等。如果索引相等,则表示该值只能出现一次。

    1
    2
    3
    4
    5
    6
    7
    var values = [1, 2, 3, 4, 5, 2, 4, 6, 2, 1, 5];

    var unique = values.filter(function(value) {
      return values.indexOf(value) === values.lastIndexOf(value);
    });

    console.log(unique); // [3, 6]

    基于我误解问题的反馈,这里有一种替代方法,它将从值数组返回唯一的、非重复的值。

    1
    2
    3
    4
    5
    6
    var values = [1, 2, 3, 4, 5, 2, 4, 6, 2, 1, 5];
    var unique = values.reduce(function(unique, value) {
      return unique.indexOf(value) === -1 ? unique.concat([value]) : unique;
    }, []);

    console.log(unique); // [1, 2, 3, 4, 5, 6]


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    var numbers = [1, 1, 2, 3, 4, 4];

    function unique(dupArray) {
      return dupArray.reduce(function(previous, num) {

        if (previous.find(function(item) {
            return item == num;
          })) {
          return previous;
        } else {
          previous.push(num);
          return previous;
        }
      }, [])
    }

    var check = unique(numbers);
    console.log(check);


    我知道这已经是死路一条了…但是…没有人提到过linq的javascript实现。然后,可以使用.distinct()方法,这使得代码非常容易阅读。

    1
    2
    3
    4
    5
    var Linq = require('linq-es2015');
    var distinctValues =  Linq.asEnumerable(testValues)
                .Select(x)
                .distinct()
                .toArray();

    1
    2
    3
    4
    5
    6
    7
    var testValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];

    var distinctValues = Enumerable.asEnumerable(testValues)
      .distinct()
      .toArray();

    console.log(distinctValues);
    1
    <script src="https://npmcdn.com/linq-es5/dist/linq.js">


    我有一个使用ES6 reduce and find array helper方法删除重复项的解决方案。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let numbers = [2, 2, 3, 3, 5, 6, 6];

    const removeDups = array => {
      return array.reduce((acc, inc) => {
        if (!acc.find(i => i === inc)) {
          acc.push(inc);
        }
        return acc;
      }, []);
    }

    console.log(removeDups(numbers)); /// [2,3,5,6]


    这是一个ES6函数,它从对象数组中删除重复项,并按指定的对象属性进行筛选。

    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
    function dedupe(arr = [], fnCheck = _ => _) {
      const set = new Set();
      let len = arr.length;

      for (let i = 0; i < len; i++) {
        const primitive = fnCheck(arr[i]);
        if (set.has(primitive)) {
          // duplicate, cut it
          arr.splice(i, 1);
          i--;
          len--;
        } else {
          // new item, add it
          set.add(primitive);
        }
      }

      return arr;
    }

    const test = [
        {video:{slug:"a"}},
        {video:{slug:"a"}},
        {video:{slug:"b"}},
        {video:{slug:"c"}},
        {video:{slug:"c"}}
    ]
    console.log(dedupe(test, x => x.video.slug));

    // [{video:{slug:"a"}}, {video:{slug:"b"}}, {video:{slug:"c"}}]


    1
    2
    3
    4
    5
    6
    7
    8
    Array.prototype.unique = function() {
        var a = [],k = 0,e;
        for(k=0;e=this[k];k++)
          if(a.indexOf(e)==-1)
               a.push(e);
        return a;
    }
    [1,2,3,4,33,23,2,3,22,1].unique(); // return [1,2,3,4,33,23,22]

    另一个解决方案。

    我最近需要使排序的列表唯一,我使用过滤器跟踪这样一个对象中的前一项:

    1
    2
    3
    4
    5
    uniqueArray = sortedArray.filter(function(e) {
        if(e==this.last)
          return false;
        this.last=e; return true;  
      },{last:null});

    类似于@sergeyz解决方案,但通过使用更多的速记格式(如arrow函数和array.includes格式)更紧凑。警告:由于使用了逻辑"或"和"逗号",jslint将投诉。(但仍然完全有效的javascript)

    1
    my_array.reduce((a,k)=>(a.includes(k)||a.push(k),a),[])

    这个脚本修改数组,过滤掉重复的值。它适用于数字和字符串。

    网址:https://jsfiddle.net/qsdl6y5j/1/

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        Array.prototype.getUnique = function () {
            var unique = this.filter(function (elem, pos) {
                return this.indexOf(elem) == pos;
            }.bind(this));
            this.length = 0;
            this.splice(0, 0, unique);
        }

        var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
        duplicates.getUnique();
        alert(duplicates);

    相反,此版本允许您返回一个新数组,该数组具有保持原始值的唯一值(仅传递true)。

    https://jsfiddle.net/dj7qxyl7/

    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
        Array.prototype.getUnique = function (createArray) {
            createArray = createArray === true ? true : false;
            var temp = JSON.stringify(this);
            temp = JSON.parse(temp);
            if (createArray) {
                var unique = temp.filter(function (elem, pos) {
                    return temp.indexOf(elem) == pos;
                }.bind(this));
                return unique;
            }
            else {
                var unique = this.filter(function (elem, pos) {
                    return this.indexOf(elem) == pos;
                }.bind(this));
                this.length = 0;
                this.splice(0, 0, unique);
            }
        }

        var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
        console.log('++++ ovveride')
        duplicates.getUnique();
        console.log(duplicates);
        console.log('++++ new array')
        var duplicates2 = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
        var unique = duplicates2.getUnique(true);
        console.log(unique);
        console.log('++++ original')
        console.log(duplicates2);
    1
    2
    3
    4
    Browser support:

    Feature Chrome  Firefox (Gecko)     Internet Explorer   Opera   Safari
    Basic support   (Yes)   1.5 (1.8)   9                   (Yes)   (Yes)


    您可以使用Ramda.js(一个功能性的javascript库)来执行此操作:

    1
    2
    var unique = R.uniq([1, 2, 1, 3, 1, 4])
    console.log(unique)
    1
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js">


    使用字段[2]作为ID生成唯一数组的数组:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    const arr = [
      ['497', 'Q0', 'WTX091-B06-138', '0', '1.000000000', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B09-92', '1', '0.866899288', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B09-92', '2', '0.846036819', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B09-57', '3', '0.835025326', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B43-79', '4', '0.765068215', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B43-56', '5', '0.764211464', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B44-448', '6', '0.761701704', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B44-12', '7', '0.761701704', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B49-128', '8', '0.747434800', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B18-17', '9', '0.746724770', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B19-374', '10', '0.733379549', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B19-344', '11', '0.731421782', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B09-92', '12', '0.726450470', 'GROUP001'],
      ['497', 'Q0', 'WTX091-B19-174', '13', '0.712757036', 'GROUP001']
    ];


    arr.filter((val1, idx1, arr) => !!~val1.indexOf(val1[2]) &&
      !(arr.filter((val2, idx2) => !!~val2.indexOf(val1[2]) &&
        idx2 < idx1).length));

    console.log(arr);


    如果您有一个对象数组,并且需要一个uniqueBy函数,例如,通过一个id字段:

    1
    2
    3
    4
    5
    6
    function uniqueBy(field, arr) {
       return arr.reduce((acc, curr) => {
         const exists = acc.find(v => v[field] === curr[field]);
         return exists ? acc : acc.concat(curr);
       }, [])
    }

    可以使用数组的helper函数reduce()和some()来获得结果。检查我的代码段:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var arrayWithDuplicates = [0, 0, 1, 2, 3, 3, 4, 4, 'a', 'a', '', '', null, null];

    var arrayWithUniqueValues = arrayWithDuplicates
                                .reduce((previous, item) => {
                                    if(!previous.some(element => element === item)) {
                                        previous.push(item)
                                    }
                                    return previous;
                                }, []);

    console.log('arrayWithUniqueValues', arrayWithUniqueValues)


    对字符串使用.toString()。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var givenvalues = [1,2,3,3,4,5,6];
    var values = [];
    for(var i=0; i<givenvalues.length; i++)
    {
        if(values.indexOf(givenvalues[i]) == -1)
        {
            values[values.length] = givenvalues[i];
        }
    }

    另一个答案,仅仅因为我为我的特定用例写了一个。不管怎样,我碰巧正在对数组进行排序,而且考虑到我正在进行排序,我可以使用它来消除重复。

    注意,我的排序处理特定的数据类型,您可能需要一个不同的排序,这取决于您拥有的元素的类型。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var sortAndDedup = function(array) {
      array.sort(function(a,b){
        if(isNaN(a) && isNaN(b)) { return a > b ? 1 : (a < b ? -1 : 0); }
        if(isNaN(a)) { return 1; }
        if(isNaN(b)) { return -1; }
        return a-b;
      });

      var newArray = [];
      var len = array.length;
      for(var i=0; i<len; i++){
        if(i === 0 || array[i] != array[i-1]){
          newArray.push(array[i]);
        }
      }
    };


    如果顺序不重要,那么我们可以创建一个散列并获取使数组唯一的键。

    1
    2
    3
    4
    var ar = [1,3,4,5,5,6,5,6,2,1];
    var uarEle = {};
    links.forEach(function(a){ uarEle[a] = 1; });
    var uar = keys(uarEle)

    UAR将具有唯一的数组元素。


    我看了JoeyTje50关于JSPerf的代码,他比较了许多替代方案。他的代码有许多小错误,这在性能和正确性上造成了不同。

    更重要的是,他正在一个非常小的阵列上进行测试。我做了一个包含1000个整数的数组。每个整数是0到1000之间的随机整数的100倍。平均约1000个/e=368个副本。结果在JSPERF中。

    这是一个更现实的场景,其中可能需要效率。这些变化对声明做出了巨大的改变(特别是被吹捧为"最快"的代码根本就不快)。最明显的赢家是使用散列技术的地方,最好的是

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Array.prototype.getUnique3 = function(){
       var u = Object.create(null), a = [];
       for(var i = 0, l = this.length; i < l; ++i){
          if(this[i] in u) continue;
          a.push(this[i]);
          u[this[i]] = 1;
       }
       return a.length;
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var a = [1,4,2,7,1,5,9,2,4,7,2]
    var b = {}, c = {};
    var len = a.length;
    for(var i=0;i<len;i++){
      a[i] in c ? delete b[a[i]] : b[a[i]] = true;
      c[a[i]] = true;
    }

    // b contains all unique elements


    这个解决方案应该非常快,并且在许多情况下都可以工作。

  • 将索引数组项转换为对象键
  • 使用object.keys函数

    1
    2
    3
    4
    var indexArray = ["hi","welcome","welcome",1,-9];
    var keyArray = {};
    indexArray.forEach(function(item){ keyArray[item]=null; });
    var uniqueArray = Object.keys(keyArray);

  • 过滤掉未定义和空值,因为大多数时候您不需要它们。

    1
    const uniques = myArray.filter(e => e).filter((e, i, a) => a.indexOf(e) === i);

    1
    const uniques = [...new Set(myArray.filter(e => e))];

    有时我需要从一组对象中获得唯一的实例。Lodash看起来是个不错的助手,但我认为过滤数组并不能证明向项目添加依赖项是正确的。

    让我们假设在比较属性(例如ID)时比较两个对象的姿势。

    const a = [{id: 3}, {id: 4}, {id: 3}, {id: 5}, {id: 5}, {id: 5}];

    既然我们都喜欢一行代码片段,那么就可以这样做:

    a.reduce((acc, curr) => acc.find(e => e.id === curr.id) ? acc : [...acc, curr], [])


    在我使用对象的用例中,上面的对象答案似乎对我不起作用。

    我修改如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var j = {};

    this.forEach( function(v) {
       var typ = typeof v;
       var v = (typ === 'object') ? JSON.stringify(v) : v;

       j[v + '::' + typ] = v;
    });

    return Object.keys(j).map(function(v){
      if ( v.indexOf('::object') > -1 ) {
        return JSON.parse(j[v]);
      }

      return j[v];
    });

    现在,对于对象、数组、混合值数组、布尔值数组等,这似乎可以正常工作。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    (function() {
       "use strict";

        Array.prototype.unique = function unique() {
            var self = this;
            return self.filter(function(a) {
                var that = this;
                // console.log(that);
                return !that[a] ? that[a] = true : false;
            }, {});
        }

        var sampleArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
        var distinctArray = sampleArray.unique();
        console.log(distinctArray);
    })();
    1
    Here is the simple way to solve this problem...


    对于字符串数组:

    1
    2
    3
    4
    5
    6
    7
    function removeDuplicatesFromArray(arr) {
      const unique = {};
      arr.forEach((word) => {
        unique[word] = 1; // it doesn't really matter what goes here
      });
      return Object.keys(unique);
    }

    如果要就地更改(而不是创建新数组),您只需:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    var
      uniq = function uniq(array) {
        var
          len = array.length;

        while (len--) {
          if (array.indexOf(array[len]) !== len) {
            array.splice(len, 1);
          }
        }

        return array;
      },

      myArray = [1, 2, 2, 4, 2];

    console.log(uniq(myArray));
    // [1, 2, 4];


    不要引用我的话,但我认为你需要在你的属性名上使用一个字符串,比如o[e.toString()],然后在你推它的时候把它转换回来。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     Array.prototype.unique=function(){

       var cr=[];

      this.forEach(function(entry) {
       if(cr.indexOf(entry)<0){
         cr.push(entry);
       }else{
        var index = cr.indexOf(entry);
        if (index > -1) {
         cr.splice(index, 1);
          }
       }

     });

     return cr;
    }

    我使用数组reduce作为创建数组唯一性的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Array.prototype.unique = function() {
      var object = this.reduce(function(h, v) {
        h[v] = true;
        return h;
      }, {});
      return Object.keys(object);
    }

    console.log(["a","b","c","b","c","a","b"].unique()); // => ["a","b","c"]