我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
我需要删除重复项并将唯一值放入新数组。
我可以指出我尝试过的所有代码,但我认为它们没有用,因为它们不起作用。我也接受jQuery解决方案。
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
我需要删除重复项并将唯一值放入新数组。
我可以指出我尝试过的所有代码,但我认为它们没有用,因为它们不起作用。我也接受jQuery解决方案。
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
当前回答
我已经在其他问题上对消除重复进行了详细的比较,但注意到这是真实的地方,我也想在这里分享一下。
我相信这是最好的方法
var-myArray=[100,200,100,100,200,200,200],reduced=Object.keys(myArray.reduce((p,c)=>(p[c]=true,p),{}));console.log(减少);
好啊尽管这一个是O(n),其他是O(n^2),但我很好奇地看到这个reduce/look up表和filter/indexOf组合之间的基准比较(我选择了非常好的Jetendras实现https://stackoverflow.com/a/37441144/4543207). 我准备了一个100K的项目数组,其中填充了0-9999范围内的随机正整数,并删除了重复项。我重复了10次测试,结果的平均值表明他们在性能上不匹配。
在firefox v47中,reduce和lut:14.85ms vs filter和indexOf:2836ms在铬v51中,reduce和lut:23.90ms vs filter和indexOf:1066ms
好吧,到目前为止还不错。但是,让我们这次在ES6风格中正确地完成它。看起来很酷。。!但到目前为止,它将如何对抗强大的lut解决方案对我来说是一个谜。让我们先看看代码,然后对其进行基准测试。
var-myArray=[100,200,100,100,200,200,200],reduce=[…myArray.reduce((p,c)=>p.set(c,true),new Map()).keys()];console.log(减少);
哇,太短了。。!但表演怎么样。。?它很美。。。由于过滤器/indexOf的重量超过了我们的肩,现在我可以测试范围为0..9999的1M个正整数随机项,以获得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=[],计数=10;for(变量i=0;i<count;i++){ranar=(new Array(1000000).fill(true)).map(e=>Math.floor(Math.random()*100000));ts=performance.now();res1=红色1(ranar);te=performance.now();平均推力(te ts);ts=performance.now();res2=red2(ranar);te=performance.now();平均推力(te ts);}avg1=avg1。减少((p,c)=>p+c)/计数;avg2=avg2.减少((p,c)=>p+c)/计数;console.log(“reduce&luttake:”+avg1+“msec”);console.log(“map&spread take:”+avg2+“msec”);
你会用哪一个。。?别那么快。。。!不要上当受骗。贴图处于置换状态。现在看。。。在上述所有情况下,我们用范围<n的数字填充一个大小为n的数组。如果我们用随机数0..9999填充大小为100的数组。现在让我们在家看地图游戏。这一次是一个100K项的数组,但随机数范围为0..10M。我们将进行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=[],计数=100;for(变量i=0;i<count;i++){ranar=(new Array(100000).fill(true)).map(e=>Math.floor(Math.random()*1000000));ts=performance.now();res1=红色1(ranar);te=performance.now();平均推力(te ts);ts=performance.now();res2=red2(ranar);te=performance.now();平均推力(te ts);}avg1=avg1。减少((p,c)=>p+c)/计数;avg2=avg2.减少((p,c)=>p+c)/计数;console.log(“reduce&luttake:”+avg1+“msec”);console.log(“map&spread take:”+avg2+“msec”);
现在,这是Map()的惊人回归。。!也许现在,当你想删除重复时,你可以做出更好的决定。
好吧,我们现在都很开心。但主角总是在一些掌声中走到最后。我相信你们中的一些人想知道Set对象会做什么。既然我们对ES6开放,而且我们知道Map是前几场比赛的赢家,那么让我们将Map与Set进行比较作为决赛。这是一场典型的皇家马德里vs巴塞罗那的比赛。。。还是这样?让我们看看谁会赢得el classico:)
var ranar=[],red1=a=>reduce=[…a.reduce((p,c)=>p.set(c,true),new Map()).keys()],red2=a=>Array.from(新集合(a)),avg1=[],avg2=[],ts=0,te=0,res1=[],res2=[],计数=100;for(变量i=0;i<count;i++){ranar=(new Array(100000).fill(true)).map(e=>Math.floor(Math.random()*100000));ts=performance.now();res1=红色1(ranar);te=performance.now();平均推力(te ts);ts=performance.now();res2=red2(ranar);te=performance.now();平均推力(te ts);}avg1=avg1。减少((p,c)=>p+c)/计数;avg2=avg2.减少((p,c)=>p+c)/计数;console.log(“map&spread take:”+avg1+“msec”);console.log(“set&A.from take:”+avg2+“msec”);
哇!成年男子出乎意料的是,它根本就不是一个古典音乐。更像巴塞罗那FC对阵CA Osasuna:))
其他回答
此解决方案使用了一个新数组和函数内部的对象映射。它所做的就是循环遍历原始数组,并将每个整数添加到对象映射中
`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]
使用本机javascript函数从数组中删除重复项的最简洁方法是使用以下序列:
vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])
在reduce函数中不需要slice或indexOf,就像我在其他示例中看到的那样!将其与过滤器功能一起使用是有意义的,尽管:
vals.filter(function(v, i, a){ return i == a.indexOf(v) })
ES6(2015)的另一种方法是:
Array.from(new Set(vals))
或者甚至使用扩展运算符:
[...new Set(vals)]
干杯
对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);
});
}
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.",
];
下面的测试比列出的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