# 数组去重
# 双重 for
function unique(array) {
var arr = [];
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < arr.length; j++) {
if (array[i] === arr[j]) {
break;
}
if (j === arr.length) {
arr.push(array[i]);
}
}
}
}
var array = [1, 1, '1', '1'];
unique(array); // [1, '1']
优点:兼容性好。
缺点:不能对 NaN 和 对象去重。
var array = [NaN, NaN];
unique(array); //[NaN, NaN];
NaN 不等于 NaN。
var array = [{a: 1}, {a: 1}]
对象 不等于 对象
# indexOf
用 indexOf 来简化内层 for 循环
function unique(array) {
var arr = [];
for (var i = 0; i < array.length; i++) {
if (arr.indexOf(array[i]) === -1) {
arr.push(array[i]);
}
}
}
优点:indexOf 比两层 for 性能要好。
缺点:不能对 NaN 和 对象去重。 在 indexOf 内部也是用 === 来判断的。
var array = [NaN, NaN];
unique(array); //[NaN, NaN];
NaN 不等于 NaN。
var array = [{a: 1}, {a: 1}]
对象 不等于 对象
# 排序去重
function unique(array) {
var arr = [];
var sortArray = [].concat().sort();
var previous;
for (var i = 0; i < array.length; i++) {
if (!i || previous !== sortArray[i]) {
arr.push(sortArray[i]);
}
previous = sortArray[i];
}
}
优点:排序好再去比较要比 indexOf 更好。
缺点:对象和 NaN 不去重。 还是因为 === 的原因。
注意:sort 排序可能对有些类型是不能正常排序的。
# filter (简化外层循环)
var array = [1, 2, 1, 3];
function unique(array) {
var res = array.filter((item, index, array) => {
return array.indexOf(item) === index;
})
console.log(res);
}
unique(array);
我们需要判断当前元素从起点找是否还是原来的位置,如果是就代表第一次出现,我们就过滤出来,如果不是第一次出现,我们就开始下一次。
优点:简化了外层的 for 循环,效率要更好一点。
缺点:indexOf 内部也是使用全等,所以不能够判断 对象和 NaN 。
# 排序 + filter
function unique(array) {
return array.concat().sort().filter((item, index, array) => {
return !index || item !== array[index - 1];
})
}
通过排序后,只需要对比前一个与后一个是否相等。
缺点:使用全等,所以不能够判断 对象和 NaN 。
# object 键值对
function unique() {
var obj = {};
return array.filter((item, index, array) => {
return obj.hasOwnProperty(item) ? false : (obj[item] = true);
})
}
缺点:1 和 ‘1’ 是会被转为字符串的,所以会判为同一个值, 也不能判断对象.
# 改进 object 键值对 (识别 1, ‘1’)
function unique(array) {
var obj = {};
return array.filter((item, index, array) => {
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true);
})
}
可以辨别 1 , -1 。 存储格式为 {string1: '', number1: ''};
对象都会存为: {Object[object Object] : {}} 不能够识别对象。
# 改进 object 键值对 识别object
使用 JSON.stringify 将对象序列化。
function unique(array) {
var obj = {};
return array.filter((item, index, array) => {
return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true);
})
}
现在就可以识别两个对象来,但是 JSON.stringify 在序列的过程中,如果存在函数,正则表达式都会忽略。
# ES6
function unique(array) {
return Array.from(new Set(array));
}
可以利用 Set 去重的特性,利用 Array.from 可以将类数组和可迭代对象转为数组。
对象不去重 NaN 去重. 它是能够识别 NaN 的。