我有一组数字,我需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它工作得很好,直到数组中有一个零。我在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数组中删除重复值
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
我想从对象数组中删除重复项。重复项具有相同的ID。这是我所做的。
// prev data
const prev = [
{
id: 1,
name: "foo",
},
{
id: 2,
name: "baz",
},
{
id: 1,
name: "foo",
},
];
// method:
// Step 1: put them in an object with the id as the key. Value of same id would get overriden.
// Step 2: get all the values.
const tempObj = {};
prev.forEach((n) => (tempObj[n.id] = n));
const next = Object.values(tempObj);
// result
[
{
id: 1,
name: "foo",
},
{
id: 2,
name: "baz",
}
];
很多人已经提到使用。。。
[...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包
您也可以使用sugar.js:
[1,2,2,3,1].unique() // => [1,2,3]
[{id:5, name:"Jay"}, {id:6, name:"Jay"}, {id: 5, name:"Jay"}].unique('id')
// => [{id:5, name:"Jay"}, {id:6, name:"Jay"}]
我将所有答案分成4种可能的解决方案:
使用对象{}防止重复使用助手数组[]使用筛选器+indexOf奖金ES6设置方法。
以下是答案中的示例代码:
使用对象{}防止重复
function uniqueArray1( ar ) {
var j = {};
ar.forEach( function(v) {
j[v+ '::' + typeof v] = v;
});
return Object.keys(j).map(function(v){
return j[v];
});
}
使用助手数组[]
function uniqueArray2(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
a.push(arr[i]);
return a;
}
使用筛选器+indexOf
function uniqueArray3(a) {
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
// usage
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']
return unique;
}
使用ES6[…新集合(a)]
function uniqueArray4(a) {
return [...new Set(a)];
}
我想知道哪一个更快。我已经制作了测试功能的GoogleSheet样本。注意:ECMA 6在Google Sheets中不可用,所以我无法测试它。
以下是测试结果:
我希望看到使用对象{}的代码将获胜,因为它使用哈希。因此,我很高兴测试在Chrome和IE中显示了该算法的最佳结果。感谢@rab的代码。
2020年更新
启用谷歌脚本的ES6引擎。现在我用Sets测试了最后一段代码,它看起来比对象方法更快。
魔术
a.filter(e=>!(t[e]=e in t))
O(n)性能-我们假设您的阵列位于a中,且t={}。此处解释(+Jeppe impr.)
让unique=(a,t={})=>a.filter(e=>!(t〔e〕=e in t));//使用全局t的“单机”版本://a1.过滤器((t={},e=>!(t[e]=e in t));//测试数据设a1=[5,6,0,4,9,2,3,5,0,3,4,1,5,4,9];设a2=[[2,17],[2,17]、[2,17]、[1,12]、[5,9]、[1,12]、[6,2],[1,12]];设a3=[“迈克”、“亚当”、“马特”、“南希”、“亚当斯”、“珍妮”、“南茜”、“卡尔”];//结果console.log(JSON.stringify(唯一(a1)))console.log(JSON.stringify(唯一(a2)))console.log(JSON.stringify(唯一(a3)))