我有一组数字,我需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它工作得很好,直到数组中有一个零。我在Stack Overflow上找到了另一个脚本,看起来几乎与它完全一样,但它不会失败。
所以为了帮助我学习,有人能帮我确定原型脚本哪里出错吗?
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;
}
重复问题的更多答案:
从JS数组中删除重复值
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
很多人已经提到使用。。。
[...new Set(arr)];
这是一个很好的解决方案,但我的首选是与.filter一起使用的解决方案。在我看来,filter是获取唯一值的更自然的方法。您可以有效地删除重复项,而从数组中删除元素正是过滤器的作用所在。它还允许您链接.map、.reduce和其他.filter调用。我设计了这个解决方案。。。
const unique = () => {
let cache;
return (elem, index, array) => {
if (!cache) cache = new Set(array);
return cache.delete(elem);
};
};
myArray.filter(unique());
需要注意的是,你需要一个结束,但我认为这是一个值得的权衡。就性能而言,它比我看到的使用.filter的其他解决方案更具性能,但比[…new Set(arr)]性能更差。
另请参阅我的github包
我有一个简单的例子,我们可以从数组中删除对象,
let data = new Array({id: 1},{id: 2},{id: 3},{id: 1},{id: 3});
let unique = [];
let tempArr = [];
console.log('before', data);
data.forEach((value, index) => {
if (unique.indexOf(value.id) === -1) {
unique.push(value.id);
} else {
tempArr.push(index);
}
});
tempArr.reverse();
tempArr.forEach(ele => {
data.splice(ele, 1);
});
console.log(data);
还有另一个答案,只是因为我为我的特定用例写了一个答案。我碰巧正在对阵列进行排序,如果我正在排序,我可以使用它来消除重复数据。
注意,我的排序处理我的特定数据类型,您可能需要不同的排序,这取决于您拥有的元素类型。
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]);
}
}
};
我查看了Joeytje50在jsperf上的代码,他比较了许多替代方案。他的代码有很多小错误,这对性能和正确性产生了影响。
更重要的是,他正在一个非常小的阵列上进行测试。我用1000个整数组成了一个数组。每个整数是0到1000之间的随机整数的100倍。这使得平均约1000/e=368个重复。结果在jsperf。
这是一个可能需要效率的更现实的场景。这些变化使声明发生了戏剧性的变化(特别是被吹捧为最快的代码远没有快到哪里去)。明显的赢家是使用哈希技术的地方,最好的是
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;
}