从 JS 数组中删除重复值 [duplicate]

Remove duplicate values from JS array [duplicate]

提问人:kramden88 提问时间:2/10/2012 最后编辑:starballkramden88 更新时间:9/26/2023 访问量:3016748

问:

我有一个非常简单的 JavaScript 数组,它可能包含也可能不包含重复项。

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

我需要删除重复项并将唯一值放入新数组中。

我可以指出我尝试过的所有代码,但我认为它没用,因为它们不起作用。我也接受jQuery解决方案。

类似问题:

JavaScript jQuery 数组 重复唯一

评论

95赞 Connor Leech 7/30/2014
_.uniq(peoplenames)解决了这个 lodash.com/docs#uniq
10赞 Suhail Mumtaz Awan 5/16/2017
@ConnorLeech lodash 很容易,但不是优化的方式
45赞 Asif vora 12/10/2018
最简单的方法(在我看来)是使用 Set 对象,它允许您存储任何类型的唯一值。换句话说,Set 会自动为我们删除重复项。const names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; let unique = [...new Set(names)]; console.log(unique); // 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl'
13赞 toad 2/9/2019
世界上有太多的迈克 - 为什么不删除它们呢?南希对此有所了解。
3赞 Didier68 7/2/2020
在我的解决方案中,我在过滤之前对数据进行排序: ' const result = data.sort().filter((v, idx, t) => idx==0 || v != t[idx-1]);

答:

163赞 Casey Kuball 2/10/2012 #1

Vanilla JS:使用像 Set 这样的对象删除重复项

你总是可以尝试将它放入一个对象中,然后遍历它的键:

function remove_duplicates(arr) {
    var obj = {};
    var ret_arr = [];
    for (var i = 0; i < arr.length; i++) {
        obj[arr[i]] = true;
    }
    for (var key in obj) {
        ret_arr.push(key);
    }
    return ret_arr;
}

Vanilla JS:通过跟踪已看到的值来删除重复项(订单安全)

或者,对于顺序安全版本,使用对象来存储以前看到的所有值,并在添加到数组之前根据该值检查值。

function remove_duplicates_safe(arr) {
    var seen = {};
    var ret_arr = [];
    for (var i = 0; i < arr.length; i++) {
        if (!(arr[i] in seen)) {
            ret_arr.push(arr[i]);
            seen[arr[i]] = true;
        }
    }
    return ret_arr;

}

ECMAScript 6:使用新的 Set 数据结构(顺序安全)

ECMAScript 6 添加了新的 Data-Structure,它允许您存储任何类型的值。 按插入顺序返回元素。SetSet.values

function remove_duplicates_es6(arr) {
    let s = new Set(arr);
    let it = s.values();
    return Array.from(it);
}

用法示例:

a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

b = remove_duplicates(a);
// b:
// ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]

c = remove_duplicates_safe(a);
// c:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]

d = remove_duplicates_es6(a);
// d:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]

评论

7赞 amenthes 8/26/2014
在较新的浏览器中,您甚至可以执行 .应该注意的是,这种方法仅适用于字符串,但没关系,这就是最初的问题所要求的。var c = Object.keys(b)
1赞 Ruan Mendes 5/28/2015
还应该注意的是,您可能会丢失数组的顺序,因为对象不会保持其属性的顺序。
1赞 Casey Kuball 6/24/2015
@JuanMendes我创建了一个订单安全版本,如果以前没有看到该值,它只是复制到新数组中。
0赞 kittu 10/12/2018
这条线上发生了什么??obj[arr[i]] = true;
1赞 Casey Kuball 10/12/2018
@kittu,即获取数组的第多个元素,并将其放入对象中(用作集合)。键是元素,值是 ,这完全是任意的,因为我们只关心对象的键。itrue
5930赞 42 revs, 13 users 85%georg #2

TL;博士

使用 Set 构造函数和 spread 语法

uniq = [...new Set(array)];

(请注意,var uniq 将是一个数组......new Set() 将其转换为集合,但 [... ] 再次将其变回数组)


“聪明”但天真的方式

uniqueArray = a.filter(function(item, pos) {
    return a.indexOf(item) == pos;
})

基本上,我们遍历数组,对于每个元素,检查该元素在数组中的第一个位置是否等于当前位置。显然,对于重复元素,这两个位置是不同的。

使用过滤器回调的第三个(“this array”)参数,我们可以避免数组变量的闭包:

uniqueArray = a.filter(function(item, pos, self) {
    return self.indexOf(item) == pos;
})

虽然简洁,但此算法对于大型数组(二次时间)并不是特别有效。

哈希表来救援

function uniq(a) {
    var seen = {};
    return a.filter(function(item) {
        return seen.hasOwnProperty(item) ? false : (seen[item] = true);
    });
}

这就是通常的做法。这个想法是将每个元素放在一个哈希表中,然后立即检查它是否存在。这为我们提供了线性时间,但至少有两个缺点:

  • 由于哈希键在 JavaScript 中只能是字符串或符号,因此此代码不区分数字和“数字字符串”。也就是说,将返回uniq([1,"1"])[1]
  • 出于同样的原因,所有对象都将被视为相等:将返回 .uniq([{foo:1},{foo:2}])[{foo:1}]

也就是说,如果你的数组只包含基元,而你不关心类型(例如,它总是数字),那么这个解决方案是最佳的。

两全其美

通用解决方案结合了这两种方法:它对基元使用哈希查找,对对象使用线性搜索。

function uniq(a) {
    var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];

    return a.filter(function(item) {
        var type = typeof item;
        if(type in prims)
            return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
        else
            return objs.indexOf(item) >= 0 ? false : objs.push(item);
    });
}

排序 |优时班

另一种选择是先对数组进行排序,然后删除与前一个元素相等的每个元素:

function uniq(a) {
    return a.sort().filter(function(item, pos, ary) {
        return !pos || item != ary[pos - 1];
    });
}

同样,这不适用于对象(因为所有对象都对 )。此外,我们默默地更改原始数组作为副作用 - 不好!但是,如果您的输入已经排序,则这是要走的路(只需从上面删除即可)。sortsort

独特之处在于...

有时,需要根据除相等以外的某些条件对列表进行统一,例如,过滤掉不同但共享某些属性的对象。这可以通过传递回调来优雅地完成。此“键”回调将应用于每个元素,并删除具有相等“键”的元素。由于预期返回原语,因此哈希表在这里可以正常工作:key

function uniqBy(a, key) {
    var seen = {};
    return a.filter(function(item) {
        var k = key(item);
        return seen.hasOwnProperty(k) ? false : (seen[k] = true);
    })
}

一个特别有用的是,它将删除物理上不同但“看起来”相同的对象:key()JSON.stringify

a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]

如果 不是原始的,则必须求助于线性搜索:key

function uniqBy(a, key) {
    var index = [];
    return a.filter(function (item) {
        var k = key(item);
        return index.indexOf(k) >= 0 ? false : index.push(k);
    });
}

在 ES6 中,你可以使用:Set

function uniqBy(a, key) {
    let seen = new Set();
    return a.filter(item => {
        let k = key(item);
        return seen.has(k) ? false : seen.add(k);
    });
}

或 :Map

function uniqBy(a, key) {
    return [
        ...new Map(
            a.map(x => [key(x), x])
        ).values()
    ]
}

两者都适用于非原始键。

第一个还是最后一个?

通过键删除对象时,您可能希望保留“相等”对象中的第一个或最后一个。

使用上面的变体保留第一个,并使用 保留最后一个:SetMap

function uniqByKeepFirst(a, key) {
    let seen = new Set();
    return a.filter(item => {
        let k = key(item);
        return seen.has(k) ? false : seen.add(k);
    });
}


function uniqByKeepLast(a, key) {
    return [
        ...new Map(
            a.map(x => [key(x), x])
        ).values()
    ]
}

//

data = [
    {a:1, u:1},
    {a:2, u:2},
    {a:3, u:3},
    {a:4, u:1},
    {a:5, u:2},
    {a:6, u:3},
];

console.log(uniqByKeepFirst(data, it => it.u))
console.log(uniqByKeepLast(data, it => it.u))

图书馆

下划线Lo-Dash 都提供了方法。他们的算法基本上与上面的第一个片段相似,可以归结为:uniq

var result = [];
a.forEach(function(item) {
     if(result.indexOf(item) < 0) {
         result.push(item);
     }
});

这是二次的,但也有不错的其他好处,比如包装原生,能够通过键(用他们的话来说)统一,以及对已经排序的数组的优化。indexOfiteratee

如果你正在使用jQuery,并且无法忍受任何东西,那么它就像这样:

  $.uniqArray = function(a) {
        return $.grep(a, function(item, pos) {
            return $.inArray(item, a) === pos;
        });
  }

这又是第一个代码段的变体。

性能

在 JavaScript 中,函数调用的成本很高,因此上述解决方案虽然简洁,但效率并不是特别高。为了获得最佳性能,请替换为循环并删除其他函数调用:filter

function uniq_fast(a) {
    var seen = {};
    var out = [];
    var len = a.length;
    var j = 0;
    for(var i = 0; i < len; i++) {
         var item = a[i];
         if(seen[item] !== 1) {
               seen[item] = 1;
               out[j++] = item;
         }
    }
    return out;
}

这块丑陋的代码与上面的片段 #3 相同,但速度快了一个数量级(截至 2017 年,它只有两倍的速度 - JS 核心人员做得很好!

function uniq(a) {
    var seen = {};
    return a.filter(function(item) {
        return seen.hasOwnProperty(item) ? false : (seen[item] = true);
    });
}

function uniq_fast(a) {
    var seen = {};
    var out = [];
    var len = a.length;
    var j = 0;
    for(var i = 0; i < len; i++) {
         var item = a[i];
         if(seen[item] !== 1) {
               seen[item] = 1;
               out[j++] = item;
         }
    }
    return out;
}

/////

var r = [0,1,2,3,4,5,6,7,8,9],
    a = [],
    LEN = 1000,
    LOOPS = 1000;

while(LEN--)
    a = a.concat(r);

var d = new Date();
for(var i = 0; i < LOOPS; i++)
    uniq(a);
document.write('<br>uniq, ms/loop: ' + (new Date() - d)/LOOPS)

var d = new Date();
for(var i = 0; i < LOOPS; i++)
    uniq_fast(a);
document.write('<br>uniq_fast, ms/loop: ' + (new Date() - d)/LOOPS)

ES6 (美)

ES6 提供了 Set 对象,这让事情变得简单多了:

function uniq(a) {
   return Array.from(new Set(a));
}

let uniq = a => [...new Set(a)];

请注意,与 python 不同,ES6 集是按插入顺序迭代的,因此此代码保留了原始数组的顺序。

但是,如果您需要一个具有唯一元素的数组,为什么不从一开始就使用集合呢?

发电机

一个“惰性”的、基于生成器的版本可以建立在相同的基础上:uniq

  • 从参数中获取下一个值
  • 如果已经看到,请跳过它
  • 否则,请将其生成并将其添加到已看到的值集中

function* uniqIter(a) {
    let seen = new Set();

    for (let x of a) {
        if (!seen.has(x)) {
            seen.add(x);
            yield x;
        }
    }
}

// example:

function* randomsBelow(limit) {
    while (1)
        yield Math.floor(Math.random() * limit);
}

// note that randomsBelow is endless

count = 20;
limit = 30;

for (let r of uniqIter(randomsBelow(limit))) {
    console.log(r);
    if (--count === 0)
        break
}

// exercise for the reader: what happens if we set `limit` less than `count` and why

评论

16赞 Roman Bataev 2/10/2012
filter 和 indexOf 已在 ECMAScript 5 中引入,因此这在旧的 IE 版本 (<9) 中不起作用。如果您关心这些浏览器,则必须使用具有类似功能的库(jQuery,下划线.js等)。
14赞 Michael Robinson 12/17/2012
@RoderickObrist,如果您希望页面在较旧的浏览器中运行,则可以使用
13赞 seriyPS 2/3/2013
这是解决方案,在大型阵列中运行速度可能非常慢......O(n^2)
9赞 Charles Beattie 6/16/2014
试试这个数组: . 并被完全剥离。使用代替 .["toString", "valueOf", "failed"]toStringvalueOfObject.create(null){}
10赞 Eric Nguyen 8/13/2016
有谁知道与其他解决方案相比,Set 转换解决方案的速度有多快?
517赞 Roman Bataev 2/10/2012 #3

使用 jQuery 快速而肮脏:

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniqueNames = [];
$.each(names, function(i, el){
    if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
});

评论

8赞 Casey Kuball 9/22/2017
由于这被一个有信誉的人恢复到原来的解决方案,我要再次提到:这个解决方案是 O(n^2),使其效率低下。inArray
47赞 Nick Steele 6/30/2020
我真的希望在 2020 年我们可以开始贬值 jQuery 和其他更过时的答案......Stackoverflow 在这里开始显示出一些年龄......
6赞 Chris 9/30/2020
我同意@NickSteele但我发现,如果你看选票而不是公认的答案,它确实会随着时间的推移而自然发生。最佳答案将被吸引到顶部,因为旧的已弃用答案被否决
1赞 Sajith Sajan 11/18/2020
let uniqueNames = names.filter((item, pos ,self) => self.indexOf(item) == pos);
1赞 Casey Kuball 11/29/2020
如果您使用的是 jquery,则有 $.unique,尽管它也会对结果中的项目进行排序。最好的答案在下面(从数组创建一个集合),这个答案效率低下,而且已经过时了。
76赞 Brandon Boone 6/30/2012 #4

使用下划线.js

它是一个包含大量用于操作数组的函数的库。

这是与jQuery的tux和Backbone.js的 吊带。

_.uniq

_.uniq(array, [isSorted], [iterator]) 别名:unique
生成数组的无重复版本,使用 === 测试对象 平等。如果您事先知道数组已排序,则为 isSorted 传递 true 将运行更快的算法。如果你想 基于转换计算唯一项,传递迭代器函数。

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

alert(_.uniq(names, false));

注意:Lo-Dash下划线竞争对手)也提供了类似的 .uniq 实现。

评论

2赞 Rene Wooller 11/17/2014
遗憾的是,下划线不提供定义自定义相等函数的功能。他们允许的回调是针对“迭代”函数的,例如带有参数(item、value、array)。
0赞 norbekoff 1/19/2022
[...new Set(Array)]绰绰有余的伴侣
1赞 Brandon Boone 2/2/2022
@norbekoff - 绝对,哈哈。~10年后!
21赞 Levi 1/26/2013 #5

以下内容比列出的 jQuery 方法快 80% 以上(请参阅下面的测试)。 这是几年前类似问题的答案。如果我遇到最初提出它的人,我会发布信用。 纯JS。

var temp = {};
for (var i = 0; i < array.length; i++)
  temp[array[i]] = true;
var r = [];
for (var k in temp)
  r.push(k);
return r;

我的测试用例比较:http://jsperf.com/remove-duplicate-array-tests

评论

1赞 seriyPS 2/3/2013
我在修订版 4 中添加了一个更快的版本。请审查!
2赞 imma 8/9/2013
该测试似乎没有使用数组???我添加了(另一个)一个似乎在不同浏览器上始终快速的浏览器(参见 jsperf.com/remove-duplicate-array-tests/10):for (var n = array.length, result = [array[n--]], i; n--;){ i = 数组[n]; 如果 (!(i 在结果中)) result.push(i);} 返回结果;
1赞 Mathankumar 1/30/2013 #6

这是另一种使用 jQuery 的方法,

function uniqueArray(array){
  if ($.isArray(array)){
    var dupes = {}; var len, i;
    for (i=0,len=array.length;i<len;i++){
      var test = array[i].toString();
      if (dupes[test]) { array.splice(i,1); len--; i--; } else { dupes[test] = true; }
    }
  } 
  else {
    if (window.console) console.log('Not passing an array to uniqueArray, returning whatever you sent it - not filtered!');
      return(array);
  }
  return(array);
}

作者: William Skidmore

1赞 realmag777 2/5/2013 #7
function removeDuplicates(inputArray) {
            var outputArray=new Array();

            if(inputArray.length>0){
                jQuery.each(inputArray, function(index, value) {
                    if(jQuery.inArray(value, outputArray) == -1){
                        outputArray.push(value);
                    }
                });
            }           
            return outputArray;
        }
38赞 gilly3 2/7/2013 #8

排名靠前的答案的复杂度为 ,但这可以通过使用对象作为哈希来完成:O(n²)O(n)

function getDistinctArray(arr) {
    var dups = {};
    return arr.filter(function(el) {
        var hash = el.valueOf();
        var isDup = dups[hash];
        dups[hash] = true;
        return !isDup;
    });
}

这将适用于字符串、数字和日期。如果您的数组包含对象,则上述解决方案将不起作用,因为当强制转换为字符串时,它们都将具有值(或类似值),并且不适合用作查找值。您可以通过在对象本身上设置标志来获取对象的实现:"[object Object]"O(n)

function getDistinctObjArray(arr) {
    var distinctArr = arr.filter(function(el) {
        var isDup = el.inArray;
        el.inArray = true;
        return !isDup;
    });
    distinctArr.forEach(function(el) {
        delete el.inArray;
    });
    return distinctArr;
}

2019年编辑:现代版本的 JavaScript 使这个问题更容易解决。无论您的数组是否包含对象、字符串、数字或任何其他类型,都将起作用。Set

function getDistinctArray(arr) {
    return [...new Set(arr)];
}

实现非常简单,不再需要定义函数。

评论

0赞 tusharmath 9/6/2013
您是否考虑过方法对性能的影响?
1赞 gilly3 9/10/2013
@Tushar - 你的要点给出了 404。任何排序算法都不具有复杂性。排序不会更快。O(n)
1赞 gilly3 9/11/2013
@Tushar - 该数组中没有实际的重复项。如果要从数组中删除与数组中的其他对象具有完全相同的属性和值的对象,则需要编写自定义相等性检查函数来支持它。
2赞 gilly3 9/11/2013
@Tushar - 此页面上的任何答案都不会像您的要点那样从此类数组中删除任何重复项。
1赞 Akin Hwan 12/28/2019
请注意,IE迟到了Set
156赞 HBP 2/12/2013 #9

使用数组和函数的单行版本:.filter.indexOf

arr = arr.filter(function (value, index, array) { 
  return array.indexOf(value) === index;
});

ES6 方法

arr = arr.filter((value, index, array) => 
  array.indexOf(value) === index
)

评论

5赞 neelmeg 6/22/2016
想解释一下它是如何消除欺骗的吗?
0赞 HBP 6/22/2016
@web_dev:它没有!我已经更正了之前破坏代码的编辑。希望它现在能带来更多的感觉。感谢您的提问!
23赞 Casey Kuball 10/19/2016
不幸的是,如果这是一个大数组,则性能很差 -- arr.indexOf 是 O(n),这使得该算法为 O(n^2)
1赞 loretoparisi 5/7/2021
事实上,正如@CaseyKuball所建议的那样,这个解决方案非常慢 - 见 stackoverflow.com/questions/67424599/......
0赞 Jonah 3/26/2013 #10

如果你不想包含整个库,你可以用它来添加一个任何数组都可以使用的方法:

Array.prototype.uniq = function uniq() {
  return this.reduce(function(accum, cur) { 
    if (accum.indexOf(cur) === -1) accum.push(cur); 
    return accum; 
  }, [] );
}

["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"].uniq()
0赞 Kristian Sandström 4/5/2013 #11

如果您自己创建数组,则可以通过在插入数据时进行检查来节省循环和额外的唯一过滤器;

var values = [];
$.each(collection, function() {
    var x = $(this).value;
    if (!$.inArray(x, values)) {
        values.push(x);
    }
});

评论

0赞 xonya 4/24/2015
使用 jQuery inArray 方法时要小心:它返回数组中元素的索引,而不是布尔值。查看文档:jQuery.inArray()
389赞 Christian Landgren 4/8/2013 #12

厌倦了看到所有带有for循环或jQuery的坏例子。如今,Javascript 拥有完美的工具:排序、映射和归约。

Uniq reduce,同时保持现有秩序

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

var uniq = names.reduce(function(a,b){
    if (a.indexOf(b) < 0 ) a.push(b);
    return a;
  },[]);

console.log(uniq, names) // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]

// one liner
return names.reduce(function(a,b){if(a.indexOf(b)<0)a.push(b);return a;},[]);

通过排序实现更快的 uniq

可能有更快的方法,但这种方法相当不错。

var uniq = names.slice() // slice makes copy of array before sorting it
  .sort(function(a,b){
    return a > b;
  })
  .reduce(function(a,b){
    if (a.slice(-1)[0] !== b) a.push(b); // slice(-1)[0] means last item in array without removing it (like .pop())
    return a;
  },[]); // this empty array becomes the starting value for a

// one liner
return names.slice().sort(function(a,b){return a > b}).reduce(function(a,b){if (a.slice(-1)[0] !== b) a.push(b);return a;},[]);

2015 年更新:ES6 版本:

在 ES6 中,你有 Sets 和 Spread,这使得删除所有重复项变得非常容易和高效:

var uniq = [ ...new Set(names) ]; // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]

按发生次数排序:

有人问如何根据有多少个唯一名称对结果进行排序:

var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

var uniq = names
  .map((name) => {
    return {count: 1, name: name}
  })
  .reduce((a, b) => {
    a[b.name] = (a[b.name] || 0) + b.count
    return a
  }, {})

var sorted = Object.keys(uniq).sort((a, b) => uniq[a] < uniq[b])

console.log(sorted)

评论

0赞 ALx 11/25/2015
好!是否可以根据重复对象的频率对数组进行排序?因此,在上面的示例中,它被移动到修改后的数组的前面(或后面)?"Nancy"
0赞 Christian Landgren 12/3/2015
@ALx - 我更新了一个基于发生率排序的示例。
0赞 Shog9 2/5/2016
在第二个示例中,sort() 似乎被错误地调用了:如果 a < b,那么它返回的值与 a == b 相同的值,这可能会导致未排序的结果。除非你在这里做一些我错过的聪明的事情,否则应该是.sort(function(a,b){ return a > b ? 1 : a < b ? -1 : 0; })
0赞 Dave 5/20/2016
如果数据只是一个名称数组,除了消除重复项之外没有其他要求,为什么还要为排序、映射和减少而烦恼呢?只需使用一组 - 在 O(n) 时间内完成的工作。-- msdn.microsoft.com/en-us/library/dn251547
0赞 Christian Landgren 5/24/2016
@Dave是的 - 请参阅上面的示例[...new Set(names)]
5赞 vin_schumi 4/9/2013 #13

对 thg435 使用自定义比较器的出色答案略作修改:

function contains(array, obj) {
    for (var i = 0; i < array.length; i++) {
        if (isEqual(array[i], obj)) return true;
    }
    return false;
}
//comparator
function isEqual(obj1, obj2) {
    if (obj1.name == obj2.name) return true;
    return false;
}
function removeDuplicates(ary) {
    var arr = [];
    return ary.filter(function(x) {
        return !contains(arr, x) && arr.push(x);
    });
}
4赞 user3840178 7/15/2014 #14
$(document).ready(function() {

    var arr1=["dog","dog","fish","cat","cat","fish","apple","orange"]

    var arr2=["cat","fish","mango","apple"]

    var uniquevalue=[];
    var seconduniquevalue=[];
    var finalarray=[];

    $.each(arr1,function(key,value){

       if($.inArray (value,uniquevalue) === -1)
       {
           uniquevalue.push(value)

       }

    });

     $.each(arr2,function(key,value){

       if($.inArray (value,seconduniquevalue) === -1)
       {
           seconduniquevalue.push(value)

       }

    });

    $.each(uniquevalue,function(ikey,ivalue){

        $.each(seconduniquevalue,function(ukey,uvalue){

            if( ivalue == uvalue)

            {
                finalarray.push(ivalue);
            }   

        });

    });
    alert(finalarray);
});
2赞 cocco 8/2/2014 #15

这可能是从数组中永久删除重复项的最快方法之一,比这里的大多数函数快 10 倍。

function toUnique(a,b,c){               //array,placeholder,placeholder
 b=a.length;while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
  1. 测试:http://jsperf.com/wgu
  2. 演示:http://jsfiddle.net/46S7g/
  3. 更多: https://stackoverflow.com/a/25082874/2450730

如果你看不懂上面的代码,请问,读一本 JavaScript 书籍,或者这里有一些关于更短代码的解释。https://stackoverflow.com/a/21353032/2450730

评论

7赞 Mark K Cowan 11/6/2014
我猜这是由于将缩小的代码作为解决方案发布......
2赞 cat 7/26/2015
如果声称在使用 while within while 和拼接(这也是一个循环)时“最快”,那么您应该投反对票。最快的方法使用哈希映射(JS-Object)和单个循环,并且是O(n)。尝试仅使用 hasOwnProperty()、push() 和 forEach() 编写函数,它会很快。请参见:en.wikipedia.org/wiki/Big_O_notation
0赞 cocco 7/26/2015
根据我在许多其他网站上进行和阅读的测试......直接设置比 push (x[0] vs x.push()) 快得多,forEach 比 & hasOwnProperty() 慢得多,如果你不搞砸你的数组,它是无用的。但是,如果您发布更快的代码,我会很高兴。您也可以投反对票。无论如何,我以许多不同的方式编写了该函数,即使我发现这个工作也很奇怪,但这个函数在普通数组的大多数浏览器中给出了最好的结果。
0赞 cocco 7/26/2015
我所说的普通数组是指在 10-100000 个元素的范围内。注意。。。同样,当我使用此功能时,我真的很乐意找到更好的方法,而且我也是尝试 avoi 无用循环的人。查看我的其他功能。
0赞 cocco 7/26/2015
另一方面,最快的是指基于此特定帖子中列出的代码的最快代码。复制并粘贴这些代码,然后自己尝试一下......这里没有一个代码比这个奇怪的whilewhile函数更快。
3赞 Willem de Wit 11/6/2014 #16

另一种无需编写大量代码即可执行此操作的方法是使用 ES5 方法:Object.keys

var arrayWithDuplicates = ['a','b','c','d','a','c'],
    deduper = {};
arrayWithDuplicates.forEach(function (item) {
    deduper[item] = null;
});
var dedupedArray = Object.keys(deduper); // ["a", "b", "c", "d"]

在函数中提取

function removeDuplicates (arr) {
    var deduper = {}
    arr.forEach(function (item) {
        deduper[item] = null;
    });
    return Object.keys(deduper);
}

评论

0赞 Oriol 12/10/2014
这是行不通的。你没有在任何地方使用。arrayWithDuplicates
0赞 Willem de Wit 12/11/2014
@Oriol 对不起,我忘了一句话。我编辑了这个例子。
16赞 drew7721 12/4/2014 #17

这是这个问题的简单答案。

var names = ["Alex","Tony","James","Suzane", "Marie", "Laurence", "Alex", "Suzane", "Marie", "Marie", "James", "Tony", "Alex"];
var uniqueNames = [];

    for(var i in names){
        if(uniqueNames.indexOf(names[i]) === -1){
            uniqueNames.push(names[i]);
        }
    }

评论

0赞 Santhosh 1/20/2016
+1 代表 。如果我们不检查它的类型,它将不适用于混合类型的数组。简单而有效的答案===
0赞 Jean-Philippe Martin 3/25/2023
应该是主要答案!
25赞 Oriol 12/10/2014 #18

在 ECMAScript 6(又名 ECMAScript 2015)中,Set 可用于过滤掉重复项。然后可以使用 spread 运算符将其转换回数组。

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
    unique = [...new Set(names)];

评论

0赞 ivoputzer 1/8/2016
Set 的构造函数实际上需要关键字new
0赞 Oriol 1/8/2016
@Ivo谢谢。以前Firefox的实现不需要,我想知道ES6草案是否改变了这种行为。new
0赞 ivoputzer 1/8/2016
某些构造函数可能确实被调用为函数,尽管这种行为取决于浏览器对规范;)的实现
1赞 nondescript 12/14/2014 #19

删除字符串重复项的最简单方法是使用关联数组,然后遍历关联数组以恢复列表/数组。

如下图所示:

var toHash = [];
var toList = [];

// add from ur data list to hash
$(data.pointsToList).each(function(index, Element) {
    toHash[Element.nameTo]= Element.nameTo;
});

// now convert hash to array
// don't forget the "hasownproperty" else u will get random results 
for (var key in toHash)  {
    if (toHash.hasOwnProperty(key)) { 
      toList.push(toHash[key]);
   }
}

瞧,现在重复的不见了!

2赞 user3449311 2/5/2015 #20

删除重复项的最简单方法是执行 for 循环并比较不相同的元素并将它们推送到新数组中

 var array = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

 var removeDublicate = function(arr){
 var result = []
 var sort_arr = arr.sort() //=> optional
 for (var i = 0; i < arr.length; i++) {
        if(arr[ i + 1] !== arr[i] ){
            result.push(arr[i])
        }
 };
  return result
}  
console.log(removeDublicate(array))
==>  ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]
23赞 Juhan 2/27/2015 #21

选择这个:

var uniqueArray = duplicateArray.filter(function(elem, pos) {
    return duplicateArray.indexOf(elem) == pos;
}); 

现在 uniqueArray 不包含重复项。

5赞 GibboK 3/10/2015 #22

以下脚本返回一个仅包含唯一值的新数组。它适用于字符串和数字。不需要额外的库,只需要 vanilla JS。

浏览器支持:

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

https://jsfiddle.net/fzmcgcxv/3/

var duplicates = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl","Mike","Mike","Nancy","Carl"]; 
var unique = duplicates.filter(function(elem, pos) {
    return duplicates.indexOf(elem) == pos;
  }); 
alert(unique);
1赞 NYTom 4/5/2015 #23

我知道我有点晚了,但这是使用 jinqJs 的另一种选择

查看 Fiddle

var result = jinqJs().from(["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]).distinct().select();
5赞 Shankar ARUL 6/1/2015 #24

如果您有机会使用

D3.js

你可以做

d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]

https://github.com/mbostock/d3/wiki/Arrays#set_values

评论

0赞 Vijay Kumar Kanta 5/11/2019
很漂亮,但加载完整的强大可视化库以仅过滤重复项似乎有点矫枉过正。幸运的是,我需要库来达到某种目的,我将使用它。非常感谢。
1赞 y2knoproblem 6/25/2015 #25

嵌套循环方法,用于删除数组中的重复项并保留元素的原始顺序。

var array = [1, 3, 2, 1, [5], 2, [4]]; // INPUT

var element = 0;
var decrement = array.length - 1;
while(element < array.length) {
  while(element < decrement) {
    if (array[element] === array[decrement]) {
      array.splice(decrement, 1);
      decrement--;
    } else {
      decrement--;
    }
  }
  decrement = array.length - 1;
  element++;
}

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

解释: 内部循环将数组的第一个元素与所有其他元素进行比较,这些元素以最高索引的元素开头。向第一个元素递减,从数组中拼接出一个副本。

当内部循环完成时,外部循环将递增到下一个元素进行比较,并重置数组的新长度。

0赞 cat 7/26/2015 #26

复杂度为 O(n) 的 Vanilla JS 解决方案(此问题可能最快)。如果需要,修改 hashFunction 以区分对象(例如 1 和“1”)。第一种解决方案避免了隐藏循环(在 Array 提供的函数中很常见)。

var dedupe = function(a) 
{
    var hash={},ret=[];
    var hashFunction = function(v) { return ""+v; };
    var collect = function(h)
    {
        if(hash.hasOwnProperty(hashFunction(h)) == false) // O(1)
        {
            hash[hashFunction(h)]=1;
            ret.push(h); // should be O(1) for Arrays
            return;
        }
    };

    for(var i=0; i<a.length; i++) // this is a loop: O(n)
        collect(a[i]);
    //OR: a.forEach(collect); // this is a loop: O(n)

    return ret;
}

var dedupe = function(a) 
{
    var hash={};
    var isdupe = function(h)
    {
        if(hash.hasOwnProperty(h) == false) // O(1)
        {
            hash[h]=1;
            return true;
        }

        return false;
    };

    return a.filter(isdupe); // this is a loop: O(n)
}
4赞 THE AMAZING 8/18/2015 #27

https://jsfiddle.net/2w0k5tz8/

function remove_duplicates(array_){
    var ret_array = new Array();
    for (var a = array_.length - 1; a >= 0; a--) {
        for (var b = array_.length - 1; b >= 0; b--) {
            if(array_[a] == array_[b] && a != b){
                delete array_[b];
            }
        };
        if(array_[a] != undefined)
            ret_array.push(array_[a]);
    };
    return ret_array;
}

console.log(remove_duplicates(Array(1,1,1,2,2,2,3,3,3)));

循环、删除重复项并创建克隆数组占位符,因为数组索引不会更新。

向后循环以获得更好的性能(您的循环不需要不断检查数组的长度)

39赞 ivoputzer 9/12/2015 #28

使用本机 javascript 函数从数组中删除重复项的最简洁方法是使用如下所示的序列:

vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])

不需要 reduce 函数,就像我在其他示例中看到的那样!不过,将它与过滤器函数一起使用是有意义的:sliceindexOf

vals.filter(function(v, i, a){ return i == a.indexOf(v) })

另一种 ES6(2015) 方法已经在一些浏览器上工作:

Array.from(new Set(vals))

甚至使用点差运算符

[...new Set(vals)]

干杯!

评论

0赞 caiohamamura 10/28/2015
对于那些习惯 python 的人来说,Set 很棒且非常直观。太糟糕了,他们没有那些伟大的(并集、相交、差异)方法。
0赞 Alexander Dixon 6/10/2016
我选择了利用该机制的简单代码行。这是用于自定义自动化任务的,所以我并不怀疑在最新版本的 Chrome(在 jsfiddle 中)使用它。但是,我仍然想知道最短的全浏览器兼容方法来消除数组重复数据。set
0赞 ivoputzer 6/10/2016
集合是新规范的一部分,您应该使用 sort/reduce 组合来确保跨浏览器兼容性@AlexanderDixon
0赞 Alexander Dixon 6/10/2016
.reduce()不跨浏览器兼容,因为我必须应用poly-fill。不过,我很欣赏你的回复。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/......
2赞 M.A.K. Ripon 11/12/2015 #29
function arrayDuplicateRemove(arr){
    var c = 0;
    var tempArray = [];
    console.log(arr);
    arr.sort();
    console.log(arr);
    for (var i = arr.length - 1; i >= 0; i--) {
        if(arr[i] != tempArray[c-1]){
            tempArray.push(arr[i])
            c++;
        }
    };
    console.log(tempArray);
    tempArray.sort();
    console.log(tempArray);
}
8赞 csuwldcat 12/19/2015 #30

除了是一个比当前答案更简单、更简洁的解决方案(减去面向未来的 ES6 解决方案)之外,我还对此进行了性能测试,它的速度也快得多:

var uniqueArray = dupeArray.filter(function(item, i, self){
  return self.lastIndexOf(item) == i;
});

需要注意的是:Array.lastIndexOf() 是在 IE9 中添加的,所以如果你需要比这更低,你需要寻找其他地方。

0赞 neelmeg 4/12/2016 #31
var duplicates = function(arr){
     var sorted = arr.sort();
   var dup = [];
   for(var i=0; i<sorted.length; i++){
        var rest  = sorted.slice(i+1); //slice the rest of array
       if(rest.indexOf(sorted[i]) > -1){//do indexOf
            if(dup.indexOf(sorted[i]) == -1)    
         dup.push(sorted[i]);//store it in another arr
      }
   }
   console.log(dup);
}

duplicates(["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]);
19赞 Redu 5/26/2016 #32

我已经在其他一些问题上对欺骗删除进行了详细的比较,但注意到这是真实的地方,我也想在这里分享它。

我相信这是最好的方法

var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
    reduced = Object.keys(myArray.reduce((p,c) => (p[c] = true,p),{}));
console.log(reduced);

还行。。尽管这个是 O(n) 而其他是 O(n^2),但我很好奇地看到这个 reduce / 查找表和 filter/indexOf 组合之间的基准比较(我选择 Jeetendras 非常好的实现 https://stackoverflow.com/a/37441144/4543207)。我准备了一个 100K 的项目数组,里面填充了 0-9999 范围内的随机正整数,并删除了重复项。我重复测试了 10 次,结果的平均值表明它们在性能上不匹配。

  • 在 firefox v47 中,reduce & lut : 14.85ms vs filter & indexOf : 2836ms
  • 在chrome v51中,reduce和lut:23.90ms与filter和indexOf:1066ms

好吧,到目前为止,一切顺利。但是,这次让我们以 ES6 风格正确地做到这一点。它看起来很酷..!但截至目前,它将如何对抗强大的 lut 解决方案对我来说是一个谜。让我们先看一下代码,然后对它进行基准测试。

var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
    reduced = [...myArray.reduce((p,c) => p.set(c,true),new Map()).keys()];
console.log(reduced);

哇,太短了..!但是性能怎么样..?真漂亮。。。由于过滤器/索引的重担举过我们的肩膀,现在我可以测试一个数组 1M 个正整数的数组,范围为 0..99999,以获得 10 次连续测试的平均值。我可以说这一次是一场真正的比赛。亲眼看看结果:)

var ranar = [],
     red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
     red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
     avg1 = [],
     avg2 = [],
       ts = 0,
       te = 0,
     res1 = [],
     res2 = [],
     count= 10;
for (var i = 0; i<count; i++){
  ranar = (new Array(1000000).fill(true)).map(e => Math.floor(Math.random()*100000));
  ts = performance.now();
  res1 = red1(ranar);
  te = performance.now();
  avg1.push(te-ts);
  ts = performance.now();
  res2 = red2(ranar);
  te = performance.now();
  avg2.push(te-ts);
}

avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;

console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");

你会用哪一个..?好吧,没那么快......!不要上当受骗。地图处于位移状态。现在看...在上述所有情况下,我们用范围 < n 的数组填充大小为 n 的数组。我的意思是我们有一个大小为 100 的数组,我们用随机数 0..9 填充,所以有明确的重复项,并且“几乎”肯定每个数字都有一个重复项。如果我们用随机数 100 填充大小为 0..9999 的数组怎么样。现在让我们看看地图在家玩。这次是 100K 项的数组,但随机数范围为 0..100M。我们将进行 100 次连续测试以平均结果。好吧,让我们看看赌注..!<-没有错别字

var ranar = [],
     red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
     red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
     avg1 = [],
     avg2 = [],
       ts = 0,
       te = 0,
     res1 = [],
     res2 = [],
     count= 100;
for (var i = 0; i<count; i++){
  ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*100000000));
  ts = performance.now();
  res1 = red1(ranar);
  te = performance.now();
  avg1.push(te-ts);
  ts = performance.now();
  res2 = red2(ranar);
  te = performance.now();
  avg2.push(te-ts);
}

avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;

console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");

现在这是Map()的壮观回归..!也许现在,当您想要删除重复时,您可以做出更好的决定。

好吧,我们现在都很开心。但主角总是排在最后,赢得一些掌声。我相信你们中的一些人想知道 Set 对象会做什么。既然我们对 ES6 持开放态度,并且我们知道 Map 是前几款游戏的赢家,那么让我们将 Map 与 Set 作为最终游戏进行比较。这次是典型的皇家马德里对阵巴塞罗那的比赛......或者是吗?让我们看看谁将赢得 el classico :)

var ranar = [],
     red1 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
     red2 = a => Array.from(new Set(a)),
     avg1 = [],
     avg2 = [],
       ts = 0,
       te = 0,
     res1 = [],
     res2 = [],
     count= 100;
for (var i = 0; i<count; i++){
  ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*10000000));
  ts = performance.now();
  res1 = red1(ranar);
  te = performance.now();
  avg1.push(te-ts);
  ts = performance.now();
  res2 = red2(ranar);
  te = performance.now();
  avg2.push(te-ts);
}

avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;

console.log("map & spread took: " + avg1 + "msec");
console.log("set & A.from took: " + avg2 + "msec");

哇。。男人。。!好吧,出乎意料的是,它根本不是经典的。更像巴塞罗那对阵奥萨苏纳:))

评论

0赞 mjwrazor 12/1/2017
顺便说一句,我在 Typescript 中尝试使用您的 ES6 方法arr.reduce(...).keys(...).slice is not a function
3赞 Isaac Pak 6/10/2016 #33

这只是另一种解决方案,但与其他解决方案不同。

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  newArr.sort();
  var finalArr = [];
  for(var i = 0;i<newArr.length;i++) {
   if(!(newArr[i] === newArr[i+1] || newArr[i] === newArr[i-1])) {
     finalArr.push(newArr[i]);
   } 
  }
  return finalArr;
}
7赞 user6445533 9/4/2016 #34

通用功能方法

以下是 ES2015 的通用且严格功能的方法:

// small, reusable auxiliary functions

const apply = f => a => f(a);

const flip = f => b => a => f(a) (b);

const uncurry = f => (a, b) => f(a) (b);

const push = x => xs => (xs.push(x), xs);

const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);

const some = f => xs => xs.some(apply(f));


// the actual de-duplicate function

const uniqueBy = f => foldl(
   acc => x => some(f(x)) (acc)
    ? acc
    : push(x) (acc)
 ) ([]);


// comparators

const eq = y => x => x === y;

// string equality case insensitive :D
const seqCI = y => x => x.toLowerCase() === y.toLowerCase();


// mock data

const xs = [1,2,3,1,2,3,4];

const ys = ["a", "b", "c", "A", "B", "C", "D"];


console.log( uniqueBy(eq) (xs) );

console.log( uniqueBy(seqCI) (ys) );

我们可以很容易地从以下方面派生或使用更快的实现:uniqueunqiueBySet

const unqiue = uniqueBy(eq);

// const unique = xs => Array.from(new Set(xs));

这种方法的优点:

  • 使用单独的比较器函数的通用解决方案
  • 声明式和简洁的实现
  • 重用其他小型通用函数

性能注意事项

uniqueBy不如带有循环的命令式实现快,但由于其通用性,它更具表现力。

如果您确定是导致应用中出现具体性能损失的原因,请将其替换为优化的代码。也就是说,首先以函数式、声明性的方式编写代码。之后,如果遇到性能问题,请尝试在导致问题的位置优化代码。uniqueBy

内存消耗和垃圾回收

uniqueBy利用隐藏在其体内的突变 ()。它重用累加器,而不是在每次迭代后将其丢弃。这样可以减少内存消耗和 GC 压力。由于这种副作用被包裹在函数内部,因此外部的一切都保持纯净。push(x) (acc)

10赞 bodich 11/12/2016 #35

这里对于理解和在任何地方(甚至在 PhotoshopScript 中)代码都非常简单。检查一下!

var peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl");

peoplenames = unique(peoplenames);
alert(peoplenames);

function unique(array){
    var len = array.length;
    for(var i = 0; i < len; i++) for(var j = i + 1; j < len; j++) 
        if(array[j] == array[i]){
            array.splice(j,1);
            j--;
            len--;
        }
    return array;
}

//*result* peoplenames == ["Mike","Matt","Nancy","Adam","Jenny","Carl"]
0赞 Matt MacPherson 12/3/2016 #36
function removeDuplicates (array) {
  var sorted = array.slice().sort()
  var result = []

  sorted.forEach((item, index) => {
    if (sorted[index + 1] !== item) {
      result.push(item)
    }
  })
  return result
}
30赞 Deke 12/25/2016 #37

到目前为止,我遇到的最简单的一个。在 es6.

 var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl", "Mike", "Nancy"]

 var noDupe = Array.from(new Set(names))

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

评论

0赞 JMichaelTX 4/7/2017
对于 Mac 用户,尽管这是一个 ES6 功能,但它可以在 macOS 10.11.6 El Capitan 中使用脚本编辑器。
0赞 Vishnu 1/20/2017 #38
var lines = ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Nancy", "Carl"];
var uniqueNames = [];

for(var i = 0; i < lines.length; i++)
{
    if(uniqueNames.indexOf(lines[i]) == -1)
        uniqueNames.push(lines[i]);
}
if(uniqueNames.indexOf(uniqueNames[uniqueNames.length-1])!= -1)

for(var i = 0; i < uniqueNames.length; i++)
{
    document.write(uniqueNames[i]);
      document.write("<br/>");
}

评论

0赞 Santosh 3/17/2017
您的代码运行良好。但是代码“uniqueNames.pop()”无缘无故地删除了最后一个数组元素。它使“Carl”不从数组中列出。
1赞 Syed M. Sannan 9/26/2023
@Santosh 是的,我现在无法编辑它,因为 StackOverflow 有太多待处理的编辑 ATM。但是,如果有人可以在任何时间点,请编辑掉该行。uniqueNames.pop()
0赞 Anand Somani 2/22/2017 #39

使用 lodash 快速简便 -var array = ["12346","12347","12348","12349","12349"]; console.log(_.uniqWith(array,_.isEqual));

10赞 ofir_aghai 3/15/2017 #40

所以选项是:

let a = [11,22,11,22];
let b = []


b = [ ...new Set(a) ];     
// b = [11, 22]

b = Array.from( new Set(a))   
// b = [11, 22]

b = a.filter((val,i)=>{
  return a.indexOf(val)==i
})                        
// b = [11, 22]
-1赞 shubham kucheria 3/22/2017 #41
var uniqueCompnies = function(companyArray) {
    var arrayUniqueCompnies = [],
        found, x, y;

    for (x = 0; x < companyArray.length; x++) {
        found = undefined;
        for (y = 0; y < arrayUniqueCompnies.length; y++) {
            if (companyArray[x] === arrayUniqueCompnies[y]) {
                found = true;
                break;
            }
        }

        if ( ! found) {
            arrayUniqueCompnies.push(companyArray[x]);
        }
    }

    return arrayUniqueCompnies;
}

var arr = [
    "Adobe Systems Incorporated",
    "IBX",
    "IBX",
    "BlackRock, Inc.",
    "BlackRock, Inc.",
];

评论

1赞 Alexey Subach 3/22/2017
请格式化整个帖子
0赞 stanislavs 3/24/2017 #42

aLinks 是一个简单的 JavaScript 数组对象。如果索引显示已删除重复记录的元素之前存在任何元素。我重复取消所有重复项。一个通道数组取消更多记录。

var srt_ = 0;
var pos_ = 0;
do {
    var srt_ = 0;
    for (var i in aLinks) {
        pos_ = aLinks.indexOf(aLinks[i].valueOf(), 0);
        if (pos_ < i) {
            delete aLinks[i];
            srt_++;
        }
    }
} while (srt_ != 0);
11赞 John Slegers 3/29/2017 #43

一种简单但有效的技术是将该方法与过滤器结合使用。filterfunction(value, index){ return this.indexOf(value) == index }

代码示例:

var data = [2,3,4,5,5,4];
var filter = function(value, index){ return this.indexOf(value) == index };
var filteredData = data.filter(filter, data );

document.body.innerHTML = '<pre>' + JSON.stringify(filteredData, null, '\t') +  '</pre>';

另请参阅此小提琴

评论

1赞 Pedro Ferreira 4/3/2017
天才!而且,例如,如果您想拥有重复的,(而不是删除它们),您所要做的就是替换为 Thanks!this.indexOf(value) == index this.indexOf(value, index+1) > 0
0赞 Pedro Ferreira 4/5/2017
您甚至可以将其恢复为单个“过滤器”行:filterData = data.filter((v, i) => (data.indexOf(v) == i) );
0赞 Pedro Ferreira 4/5/2017
上次我打扰了!不好意思。。。拿起我的第一个答案,在 2 行中,您可以得到一个包含重复的 JSON 以及它们重复了多少次:var JSON_dupCounter = {};data.filter((testItem, index) => (data.indexOf(testItem, index + 1) > 0)).forEach((found_duplicated) => (JSON_dupCounter[found_duplicated] = (JSON_dupCounter [found_duplicated] || 1) + 1));
0赞 frozen 7/16/2017
这仅适用于基元数组?
1赞 John Slegers 7/16/2017
@frozen : 如果适用于可用于确定相等性的所有内容。所以,如果你正在处理例如。数组、对象或函数,过滤器仅适用于引用同一数组、对象或函数的不同条目(参见演示)。如果要根据不同的条件确定相等性,则需要在筛选器中包含这些条件==
26赞 ShAkKiR 6/6/2017 #44

解决方案 1

Array.prototype.unique = function() {
    var a = [];
    for (i = 0; i < this.length; i++) {
        var current = this[i];
        if (a.indexOf(current) < 0) a.push(current);
    }
    return a;
}

解决方案 2(使用 Set)

Array.prototype.unique = function() {
    return Array.from(new Set(this));
}

测试

var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]

性能

当我在 chrome 中测试这两种实现(有和没有 Set)的性能时,我发现带有 Set 的实现要快得多!

Array.prototype.unique1 = function() {
    var a = [];
    for (i = 0; i < this.length; i++) {
        var current = this[i];
        if (a.indexOf(current) < 0) a.push(current);
    }
    return a;
}


Array.prototype.unique2 = function() {
    return Array.from(new Set(this));
}

var x=[];
for(var i=0;i<10000;i++){
	x.push("x"+i);x.push("x"+(i+1));
}

console.time("unique1");
console.log(x.unique1());
console.timeEnd("unique1");



console.time("unique2");
console.log(x.unique2());
console.timeEnd("unique2");

评论

3赞 ken 5/24/2018
对使用 Set 投赞成票。我不知道性能比较
0赞 ShAkKiR 5/25/2018
我在某处读到过 Array 比 Set(整体性能)快,但是当我在 chrome 中测试时,使用 Set 实现要快得多!查看编辑后的答案:)
0赞 ShAkKiR 6/6/2018
更好的做法是使用 Object.defineProperty(Array.prototype,“unique”.. 而不是 Array.prototype.unique = ...在此处查看更多信息 stackoverflow.com/questions/10105824/...
0赞 Demonblack 6/18/2018
Set 方法在 Node 中似乎对我不起作用。在某些情况下,new Set([5,5]) 似乎返回 [5,5]。我和你一样困惑。编辑:我发现了发生了什么。new Set([new Number(5), new Number(5)]) 返回 [5,5]。显然,如果我用新的实例化它们,Node 认为这两个数字 5 是不同的......老实说,这是我见过的最愚蠢的事情。
0赞 ShAkKiR 8/28/2018
@Demonblack 这是一个合理的担忧。x=new Number(5) 和另一个 y=new Number(5) 将是两个不同的对象,与 var x=5 和 var y=5 相反。new 关键字将创建一个新对象。我知道这个解释是显而易见的,但这就是我所知道的:)
0赞 Dan Zuzevich 6/9/2017 #45

此解决方案使用一个新数组和函数内部的对象映射。它所做的只是遍历原始数组,并将每个整数添加到对象映射中。如果在遍历原始数组时遇到重复,则

`if (!unique[int])`

捕获此属性是因为对象上已经存在具有相同编号的键属性。因此,跳过该数字并且不允许将其推送到新数组中。

    function removeRepeats(ints) {
      var unique = {}
      var newInts = []

      for (var i = 0; i < ints.length; i++) {
        var int = ints[i]

        if (!unique[int]) {
          unique[int] = 1
          newInts.push(int)
        }
      }
      return newInts
    }

    var example = [100, 100, 100, 100, 500]
    console.log(removeRepeats(example)) // prints [100, 500]
67赞 Ashutosh Jha 6/15/2017 #46

您可以简单地在 JavaScript 中完成,借助该方法的第二个 - index - 参数:filter

var a = [2,3,4,5,5,4];
a.filter(function(value, index){ return a.indexOf(value) == index });

或速记

a.filter((v,i) => a.indexOf(v) == i)

评论

0赞 frozen 7/16/2017
这仅适用于包含基元的数组?
0赞 Hitmands 7/17/2017
这应该是a.indexOf(v)==ia.indexOf(v) === a.lastIndexOf(v)
5赞 Ashutosh Jha 7/18/2017
@Hitmands你从右边比较,我从左边比较。没有别的.
0赞 Xenos 12/20/2017
也不需要变量即可工作,因为数组是 : 的第三个参数(请注意,它也适用于 ☺ )afilter[1/0, 2,1/0,2,3].filter((v,i,a) => a.indexOf(v) === i)Infinity
0赞 omeanwell 10/4/2022
如果您在地图、reduce 等之后使用它,您也可以这样做。.filter((v,i, array) => array.indexOf(v) == i)
1赞 gnujoow 6/16/2017 #47

使用reduce和find的方式。

const numbers = [1, 1, 2, 3, 4, 4];

function unique(array) {
  return array.reduce((a, b) => {
    let isIn = a.find(element => {
      return element === b;
    });
    if (!isIn) {
      a.push(b);
    }
    return a;
  }, []);
}

let ret = unique(numbers); // [1, 2, 3, 4]
console.log(ret);

4赞 Sancarn 7/7/2017 #48

尽管 ES6 解决方案是最好的,但我对没有人展示以下解决方案感到困惑:

function removeDuplicates(arr){
    o={}
    arr.forEach(function(e){
        o[e]=true
    })
    return Object.keys(o)
}

这里要记住的是,对象必须具有唯一的键。我们正在利用这一点来删除所有重复项。我本来以为这将是最快的解决方案(在 ES6 之前)。

但请记住,这也对数组进行了排序。

73赞 Jonca33 8/1/2017 #49

一行:

let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy'];
let dup = [...new Set(names)];
console.log(dup);

评论

5赞 kchetan 4/15/2018
最佳答案,如果您使用的是 ES6
0赞 Vitalicus 1/12/2022
这 3 个点是什么意思?
1赞 Debargha Roy 2/21/2022
@Vitalicus,这是 ES6 中的扩展算子。在这里阅读更多内容
9赞 Mohideen bin Mohammed 8/3/2017 #50

这里是简单的方法,没有任何特殊库的特殊功能,

name_list = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
get_uniq = name_list.filter(function(val,ind) { return name_list.indexOf(val) == ind; })

console.log("Original name list:"+name_list.length, name_list)
console.log("\n Unique name list:"+get_uniq.length, get_uniq)

enter image description here

43赞 Sumit Joshi 9/14/2017 #51

像这样使用Array.filter()

var actualArr = ['Apple', 'Apple', 'Banana', 'Mango', 'Strawberry', 'Banana'];

console.log('Actual Array: ' + actualArr);

var filteredArr = actualArr.filter(function(item, index) {
  if (actualArr.indexOf(item) == index)
    return item;
});

console.log('Filtered Array: ' + filteredArr);

在 ES6 中可以将其缩短为

actualArr.filter((item,index,self) => self.indexOf(item)==index);

这是很好的解释Array.filter()

评论

0赞 Edwin 9/14/2017
你能详细说明一下你在这里做了什么吗?:-)
2赞 DCR 3/13/2018
当数组是数组的数组时不起作用
-8赞 user1429980 9/16/2017 #52

ES2015,1 行,与 链接良好,但仅适用于整数:map

[1, 4, 1].sort().filter((current, next) => current !== next)

[1, 4]

评论

0赞 Kroltan 10/6/2017
这适用于任何内容,但只能删除顺序重复项。例如 -> 但是[1,1,2,2,3,3][1,2,3][1,2,3,1,2,3] -> [1,2,3,1,2,3]
3赞 Xenos 12/20/2017
@Kroltan 这实际上不是顺序重复的问题,而是关于理解传递给什么的一个大问题:它不是,所以它会适用于但不适用于......filter(value, index)(current, next)[1,4,1][2,4,2]
0赞 Kroltan 12/21/2017
@Xenos 你是对的!我浏览它的速度太快了 xD
0赞 scipper 11/26/2020
我认为这种方法很好,也可以很容易地适用于其他类型的数组,只需稍作修改:["1", "4", "1"].sort().filter((value, index, array) => value !== array[index + 1])
3赞 cjjenkinson 10/14/2017 #53

对于希望将具有重复元素的数组展平为一个唯一数组的任何人:

function flattenUniq(arrays) {
  var args = Array.prototype.slice.call(arguments);

  var array = [].concat.apply([], args)

  var result = array.reduce(function(prev, curr){
    if (prev.indexOf(curr) < 0) prev.push(curr);
    return prev;
  },[]);

  return result;
}

评论

0赞 Austin737 7/12/2021
在reduce方法之后添加的空数组的用途是什么?
7赞 MBJH 10/25/2017 #54
for (i=0; i<originalArray.length; i++) {  
    if (!newArray.includes(originalArray[i])) {
        newArray.push(originalArray[i]); 
    }
}

评论

0赞 Shiva T. Kota 11/26/2017
喜欢香草JS。谢谢