跳到正文
文章封面

【编程题与分析题】数组去重

数组去重

// 数组去重方法总结
// 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));

评论

填写昵称与邮箱即可评论,无需登录。

推荐阅读