从JS数组中移除重复值

2348

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

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

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

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

类似问题:


95
_.uniq(peoplenames) 解决了这个问题。请参考 http://lodash.com/docs#uniq 了解更多信息。 - Connor Leech
10
@ConnorLeech 使用 lodash 很容易,但这不是最优化的方式。 - Suhail Mumtaz Awan
45
我认为最简单的方法是使用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'` - Asif vora
13
世界上有太多叫Mike的人了——为什么不把他们移除掉呢?Nancy在这件事上被打败了。 - toad
3
在我的解决方案中,我会在过滤之前对数据进行排序:const result = data.sort().filter((v, idx, t) => idx==0 || v != t[idx-1]); - Didier68
显示剩余10条评论
54个回答

10
所以选项是:
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]

9

这里提供一种简单的方法,不需要任何特殊的库或函数。

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


8

除了未来的ES6解决方案之外,这是一个比当前答案更简单、更简洁的解决方案。我进行了性能测试,发现它也更快:

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

需要注意的是,Array.lastIndexOf() 函数是在IE9中添加的,如果你需要向下兼容更低版本的浏览器,你需要寻找其他替代方案。


7

通用的函数式方法

这里提供一个使用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) );

我们可以轻松地从unqiueBy中推导出unique,或者使用更快的实现方式,利用Set

const unqiue = uniqueBy(eq);

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

这种方法的好处:

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

性能考虑

uniqueBy不像使用循环的命令式实现那样快,但由于其泛化程度更高,因此更具表达力。

如果你发现uniqueBy在你的应用中造成了具体的性能损失,请用优化过的代码替换它。也就是说,首先以函数式、声明性的方式编写代码。接着,如果遇到性能问题,尝试在导致问题的位置优化代码。

内存消耗和垃圾回收

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


7
for (i=0; i<originalArray.length; i++) {  
    if (!newArray.includes(originalArray[i])) {
        newArray.push(originalArray[i]); 
    }
}

热爱纯JavaScript。谢谢。 - Shiva Teja

5
以下脚本返回一个新的数组,其中只包含唯一值。它适用于字符串和数字。不需要额外的库,仅使用原生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);

5

虽然加载完整的强大可视化库仅用于过滤重复项看起来很美,但这似乎有些浪费。幸运的是,我需要该库来完成某些任务,因此我将继续使用它。非常感谢。 - Vijay Kumar Kanta

5

对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
尽管 ES6 解决方案是最好的,但我很困惑为什么没有人展示以下解决方案:
function removeDuplicates(arr){
    o={}
    arr.forEach(function(e){
        o[e]=true
    })
    return Object.keys(o)
}

这里要记住的是对象必须有唯一的键。我们利用这一点来消除所有重复项。在ES6之前,我认为这将是最快的解决方案。但请记住,这也会对数组进行排序。

4
$(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);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接