我有一组数字,我需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它工作得很好,直到数组中有一个零。我在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数组中删除重复值
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
下面是另一种使用比较器的方法(我更关心干净的代码而不是性能):
const list = [
{name: "Meier"},
{name: "Hans"},
{name: "Meier"},
]
const compare = (a, b) => a.name.localeCompare(b.name);
const uniqueNames = list.makeUnique(compare);
uniqueNames.pushIfAbsent({name: "Hans"}, compare);
原型声明:
declare global {
interface Array<T> {
pushIfAbsent(item: T, compare:(a:T, b:T)=>number): number;
}
interface Array<T> {
makeUnique(compare:(a:T, b:T)=>number): Array<T>;
}
}
Array.prototype.pushIfAbsent = function <T>(this:T[], item:T, compare:(a:T, b:T)=>number) {
if (!this.find(existing => compare(existing, item)===0)) {
return this.push(item)
} else {
return this.length;
}
}
Array.prototype.makeUnique = function <T>(this:T[], compare:(a:T, b:T)=>number) {
return this.filter((existing, index, self) => self.findIndex(item => compare(existing, item) == 0) == index);
}
这里有一个几乎是一行的O(n),保留了第一个元素,并且在这里你可以将你正在uniq'ing上的字段分开。
这是函数式编程中非常常见的技术——您可以使用reduce来构建返回的数组。因为我们这样构建数组,所以我们保证得到稳定的排序,这与[…new Set(array)]方法不同。我们仍然使用Set来确保没有重复,因此我们的累加器同时包含Set和我们正在构建的数组。
常量删除重复项=(arr)=>减少(([set,acc],item)=>集合有(item)?[set,acc]:[set.add(项目),(acc.push(项目)、acc)],[新设置(),[]])[1]
上述方法适用于简单值,但不适用于对象,类似于[…new Set(array)]的分解方式。如果项目是包含id属性的对象,您应该执行以下操作:
常量删除重复项=(arr)=>减少(([set,acc],item)=>集合有(item.id)?[set,acc]:[set.add(item.id),(acc.push(item),acc)],[新设置(),[]])[1]
这个原型getUnique并不完全正确,因为如果我有一个类似于[“1”,1,2,3,4,1,“foo”]的数组,它将返回[“1“,“2”,“3”,“4”],“1”是字符串,1是整数;它们是不同的。
以下是正确的解决方案:
Array.prototype.unique = function(a){
return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 });
使用:
var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();
以上将产生[“1”,2,3,4,1,“foo”]。