我有一组数字,我需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它工作得很好,直到数组中有一个零。我在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数组中删除重复值

类似的问题:

获取数组中的所有非唯一值(即:重复/多次出现)


当前回答

这里有一个几乎是一行的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]

其他回答

最简单的方法是将值转换为字符串,以过滤嵌套的对象值。

const uniq = (arg = []) => {
  const stringifyedArg = arg.map(value => JSON.stringify(value))
  return arg.filter((value, index, self) => {
    if (typeof value === 'object')
      return stringifyedArg.indexOf(JSON.stringify(value)) === index
    return self.indexOf(value) === index
  })
}

    console.log(uniq([21, 'twenty one', 21])) // [21, 'twenty one']
    console.log(uniq([{ a: 21 }, { a: 'twenty one' }, { a: 21 }])) // [{a: 21}, {a: 'twenty one'}]

对我来说,这是最简单的解决方案

//检查数组是否相等的方法常量a=['a','B','C'].sort().toString()常量b=['A','C','b'].sort().toString()console.log(a===b);//真的//测试用例常量数据=[{组:“A”,名称:“SD”},{组:“B”,名称:“FI”},{组:“A”,名称:“SD”},{组:“B”,名称:“CO”}];//返回一个不带重复定位的新数组函数唯一(数据){return data.reduce(函数(累加器,currentValue){//转换为字符串以检查它们是否为相同的值。const currentKeys=对象.keys(currentValue).sort().toString();const currentValues=对象.values(currentValue).sort().toString();let hasObject=falsefor(累加器的常量对象){//将键和值转换为字符串,以便我们可以//看看它们是否与当前值相等constkeys=对象.keys(obj).sort().toString();const values=Object.values(obj).sort().toString();//检查键和值是否相等if(keys==currentKeys&&values==currentValues){hasObject=真}}//如果对象不存在,则推送该对象。if(!hasObject){累加器推力(currentValue)}回流蓄能器}, []);}//运行测试用例console.log(唯一(数据));//[{组:“A”,名称:“SD”},{组为“B”,名称为“FI”}、{组“B”、名称为“CO”}]

var myArray=[“a”,2,“a”、2,“b”,“1”];常量=[];myArray.forEach((t)=>!uniques.includes(t)和uniques.push(t));console.log(uniques);

使用ES6新设置

变量数组=[3,7,5,3,2,5,2,7];var unique_array=[…新集合(数组)];console.log(unique_array);//输出=[3,7,5,2]

使用For循环

变量数组=[3,7,5,3,2,5,2,7];for(var i=0;i<array.length;i++){for(变量j=i+1;j<array.length;j++){如果(array[i]===array[j]){阵列.拼接(j,1);}}}console.log(数组);//输出=[3,7,5,2]

下面是另一种使用比较器的方法(我更关心干净的代码而不是性能):

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