数组去重
// 数组去重方法总结
// v1. 双层循环去重
function unique(arr) {
let res = [];
// 外层循环遍历原始数组
for (var i = 0, arrLen = arr.length; i < arrLen; i++) {
// 内层循环遍历res数组
for (var j = 0, resLen = res.length; j < resLen; j++) {
if (arr[i] === res[j]) {
break;
}
}
// 关键点:遍历完毕之后,如果arr[i]是唯一的,那么必定满足j===resLen
if (j === resLen) {
res.push(arr[i]);
}
}
return res;
}
// 优点: 兼容性好
// v2. indexOf去重
function unique(arr) {
var res = [];
for (var i = 0, len = arr.length; i < len; i++) {
var cur = arr[i];
if (res.indexOf(cur) === -1) {
res.push(cur);
}
}
return res;
}
// 优点:使用indexOf可以简化内层循环
// v3. 先排序,然后去重
function unique(arr){
var res = [];
// 排序之后的数组
var sortedArr = arr.concat().sort();
// seen表示的是当前的比较项
var seen;
// v1
/*for (var i = 0, len = sortedArr.length; i < len; i++) {
// 从第一个元素开始,比较相邻的元素是否相同
if (!i || seen !== sortedArr[i]) {
res.push(sortedArr[i]);
}
seen = sortedArr[i];
}*/
// v2
for (var i = 0, len = sortedArr.length; i < len; i++) {
// 最后一个和undefined比较
if (sortedArr[i] !== sortedArr[i+1]) {
res.push(sortedArr[i]);
}
}
return res;
}
// v4. 封装一个unique的API【重点掌握】
function unique(arr, isSorted){
var res = [];
var seen = [];
for (var i = 0, len = arr.length; i < len; i++) {
var value = arr[i];
// 根据是否排序选择去重方式
if (isSorted) {
// 这个排序方法要学会
if (!i || seen !== value) {
res.push(value);
}
seen = value;
}
else if (res.indexOf(value) === -1) {
res.push(value);
}
}
return res;
}
// TODO: 如何把字母的大小写视为一致,比如'a'和'A',保留一个就可以了?
// v5: 去重API增强
/**
* 去重API增强
* @param arr 表示要去重的数组,必填
* @param isSorted 表示函数传入的数组是否已排过序,如果为 true,将会采用更快的方法进行去重
* @param iteratee 传入一个函数,可以对每个元素进行重新的计算,然后根据处理的结果进行去重
* @return {Array}
*/
function unique(arr, isSorted, iteratee){
var res = [];
var seen = [];
for (var i = 0, len = arr.length; i < len; i++) {
var value = arr[i];
// 处理iteratee参数
var computed = iteratee ? iteratee(value, i, arr) : value;
if (isSorted) {
if (!i || seen !== value) {
res.push(value);
}
// 更新为最新的computed数据(是经过iteratee这个函数处理之后的结果)
seen = computed;
}
else if (iteratee) {
// 处理iteratee的核心逻辑
if (seen.indexOf(computed) === -1) {
// seen里面放的是转换处理之后的数值
seen.push(computed);
// 结果里面放入的始终是数组的原始值,而不是经过转换之后的数值
res.push(value);
}
} else if (res.indexOf(value) === -1) {
// 常规去重方法
res.push(value);
}
}
return res;
}
// TODO: 使用filter函数简化外层循环?
// v6. filter简化去重逻辑
// 使用indexOf简化
function unique(arr){
var res = arr.filter(function (item, index, self) {
// indexOf实际上找到的是第一次出现的位置
return self.indexOf(item) === index;
});
return res;
}
// 使用排序去重的方法
function unique(arr) {
return arr.concat().sort().filter(function (item, index, self) {
// 后面的一项和前面的项进行比较
return !index || item !== self[index - 1];
});
}
// v7. 使用Object键值对去重(推荐使用,可以去重所有的数据类型)
function unique(arr) {
var obj = {};
var res = arr.filter(function (item) {
// 问题1: 无法区分1和'1'
// return obj.hasOwnProperty(item) ? false : (obj[item] = true);
// 问题2: 无法区分{value: 1}和{value: 2}
// { number1: true,
// stringa: true,
// stringA: true,
// number2: true,
// stringb: true,
// stringc: true,
// number3: true }
// return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true);
// 最终解决方案:使用JSON.stringfy, 先把对象序列化处理
let temp = typeof item + JSON.stringify(item);
return obj.hasOwnProperty(temp) ? false : (obj[temp] = true);
});
console.log('obj now:', obj)
return res;
}
// v8: ES6去重大法
function unique(arr){
return Array.from(new Set(arr));
}
// 代码简化1
function unique(arr){
return [...new Set(arr)];
}
// 代码简化2
var unique = (a) => [...new Set(a)];
// 使用Map去重
function unique(arr){
const seen = new Map();
return arr.filter(a => !seen.has(a) && seen.set(a, 1));
}
console.log(unique([1, 2, 3, 2, '1']))
console.log(unique([1, '1', 2, 3], true))
console.log(unique([1, 1, 'a', 'A', 2, 'b', 'c', 3, '1', {value : 1}, {value: 2}, {value: 1}], false, function (item, index, arr) {
return typeof item === 'string' ? item.toLowerCase() : item;
}))
var array = [1, 1, '1', '1', null, null, undefined, undefined, new String('1'), new String('1'), /a/, /a/, NaN, NaN];
console.log(unique(array));
评论
填写昵称与邮箱即可评论,无需登录。