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

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

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

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

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

类似的问题:

乐十三2020/03/09 21:44:53

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

Loop through, remove duplicates, and create a clone array place holder because the array index will not be updated.

Loop backward for better performance ( your loop wont need to keep checking the length of your array)

小哥Stafan2020/03/09 21:44:53

If by any chance you were using

D3.js

You could do

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

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

路易达蒙2020/03/09 21:44:53
$(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);
});
阳光乐2020/03/09 21:44:53

通用功能方法

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

我们可以轻松地uniques 派生unqiueBy或使用更快的实现Set

const unqiue = uniqueBy(eq);

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

这种方法的好处:

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

性能考量

uniqueBy 虽然没有像使用循环这样的命令式实现那样快,但是由于其通用性,它的表达方式更加丰富。

如果您确定uniqueBy是造成应用程序具体性能下降的原因,请用优化的代码代替。也就是说,首先以功能性的声明方式编写代码。此后,如果遇到性能问题,请尝试在引起问题的位置优化代码。

内存消耗和垃圾回收

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

GreenGil2020/03/09 21:44:53

除了是比当前答案更简单,更简洁的解决方案(减去具有前瞻性的ES6解决方案)之外,我进行了性能测试,并且速度也更快:

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

一个警告:在IE9中添加了Array.lastIndexOf(),因此,如果您需要降低此值,则需要查找其他地方。

卡卡西乐逆天2020/03/09 21:44:53
for (i=0; i<originalArray.length; i++) {  
    if (!newArray.includes(originalArray[i])) {
        newArray.push(originalArray[i]); 
    }
}
Mandy古一2020/03/09 21:44:53

这对于在任何地方(甚至在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"]
村村A2020/03/09 21:44:53

因此,选项为:

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]
阿飞宝儿猴子2020/03/09 21:44:53

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

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)

在此处输入图片说明

小胖泡芙2020/03/09 21:44:53

以下内容比列出的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

西里Near2020/03/09 21:44:53

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

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
    unique = [...new Set(names)];
小宇宙猪猪2020/03/09 21:44:53

这是对该问题的简单答案。

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]);
        }
    }
梅JinJin十三2020/03/09 21:44:53

解决方案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(使用设置)

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

测试

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

性能

当我测试两种实现方式(带和不带Set)的chrome性能时,我发现带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");

猪猪Jim2020/03/09 21:44:53

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

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

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

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Set

小胖Gil2020/03/09 21:44:53

去这个:

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

现在uniqueArray不包含重复项。

小宇宙老丝2020/03/09 21:44:53

最高答案的复杂度为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无论您的数组包含对象,字符串,数字还是任何其他类型,都可以使用using

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

实现是如此简单,不再需要定义功能。

樱十三2020/03/09 21:44:53

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

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

就像我在其他示例中看到的那样,没有必要slice也没有indexOfreduce函数!不过,将其与过滤器函数一起使用是有意义的:

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

ES6(2015)的另一种已在少数浏览器上运行的方式是:

Array.from(new Set(vals))

甚至使用价差运算符

[...new Set(vals)]

干杯!

阿飞小小2020/03/09 21:44:53

使用Underscore.js

它是一个包含用于操纵数组的函数的库。

这是与jQuery的晚礼服和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实现。

Davaid阳光2020/03/09 21:44:53

使用数组过滤器和indexOf函数的单行版本:

arr = arr.filter (function (value, index, array) { 
    return array.indexOf (value) == index;
});
Near小哥Green2020/03/09 21:44:53

您可以在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)
卡卡西乐逆天2020/03/09 21:44:52

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添加了新的Set数据结构,可让您存储任何类型的值。 Set.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"]
飞云西门Near2020/03/09 21:44:52

快速而肮脏的使用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);
});