数组去重
只含有数字的数组
//利用对象键名的唯一性
Array.prototype.unique = function() {
let hash = {},
ret = [],
len = this.length;
for(let i = 0; i < len; i++) {
if(!hash[this[i]]) {
hash[this[i]] = true;
ret.push(this[i]);
}
}
return ret
}
让我们来看看效果
const arr = [1, 1, 1, 2, 2, 3, 4, 5];
console.log(arr.unique()); //[1, 2, 3, 4, 5]
但我们处理的数组中往往含有字符串,我们接着来看
const arr1 = ['1', 1, 1, '2', 2, '3'];
console.log(arr1.unique());//["1", "2", "3"]
结果肯定不符合我们的要求。这和对象设置属性名方式有关。
对象有两种设置属性的方式:一种是通过’.‘来设置;另外就是通过’[]'来设置,这两种设置有什么区别呢,我们来看下面的例子。
const obj = {};
const a = {x: true};
const b = {y: false};
obj.a = 123;
obj.b = 456;
console.log(obj.a, obj.b);// 123 456
通过‘.’的方式可以得到我们想要的结果,那么来看看’[]’
const obj = {};
const a = {x: true};
const b = {y: false};
obj[a] = 123;
obj[b] = 456;
console.log(obj[a], obj[b]); //456 456
通过’[]‘设置的键名会被的调用toString方法,所以obj[a]和obj[b]其实就等于obj[’[object Object]’]。又因为键名的唯一性,后者覆盖了前者,所以两次打印的结果都是456。
利用typeof区分数字和字符串
Array.prototype.unique = function() {
let hash = {},
ret = [],
len = this.length;
for(let i = 0; i < len; i++) {
let key = typeof this[i] + this[i];
if(!hash[key]) {
hash[key] = true;
ret.push(this[i]);
}
}
return ret
}
const arr1 = ['1', 1, 1, '2', 2, '3'];
console.log(arr1.unique());//["1", 1, "2", 2, "3"]
对象中含有数组和对象
代码如下, 文字部分再补(利用Map)
Array.prototype.unique = function() {
let hash = new Map(),
ret = [],
item,
toStr = Object.prototype.toString,
len = this.length;
for(let i = 0; i < len; i++) {
if(toStr.call(this[i]) === '[object Array]' || '[object Object]') {
item = JSON.stringify(this[i]);
} else {
item = this[i];
}
if(!hash.has(item)) {
hash.set(item, true);
ret.push(this[i]);
}
}
return ret
}
const arr2 = [[1], ['1'], {a: 1}, {a: '1'}, '1', 1, {a: {a: 1}}, {a: {a: 1}}];
console.log(arr2.unique());// [[1], ['1'], {a: 1}, {a: '1'}, '1', 1, {a: {a: 1}}]