数组去重 js实现

双层循环 

双层循环,使用额外数组

var arr = [1, 6, 4, 6, 6, 4, 2, "a", "a"];
var res = [];
for (var i = 0; i < arr.length; i++) {
  for (var j = 0; j < res.length; j++) {
    if (arr[i] === res[j]) {
      break;
    }
  }
  //如果这两个数相等说明循环完了,没有相等的元素
  if (j == res.length) {
    res.push(arr[i]);
  }
}
console.log(res); //[1, 6, 4, 2, "a"]

双层循环,利用splice

双指针遍历,splice操作会改变原始数组,注意下标

for(i = 0;i<arr.length-1;i++){
    for(j = i+1;j<arr.length;){
        if(arr[i] === arr[j]){
            arr.splice(j,1)
         }else{
            j++;
         }
      }
}

排序

此方法有局限,sort后的数组形如[1,'1',1]会无法完全去重

利用sort,单层for循环 

arr.sort((a,b)=>{
    return a-b;
 })
for(let i = 0;i <arr.length-1;i++){
    if(arr[i]===arr[i+1]){
        arr.splice(i+1,1)
        i--; //注意
    }
}

// 使用额外数组
var newArr = [];
arr = arr.sort();
for (let i = 0; i < arr.length; i++) {
    if (arr[i] !== arr[i+1]) {
        newArr.push(arr[i])
    }
}
// 不同写法 
// for (let i = 1; i < arr.length; i++) {  
//    arr[i] !== arr[i-1] && newArr.push(arr[i])
//}
console.log(newArr);

sort排序+filter

var array = [1, 2, 1, 1, '1'];
function unique(array) {
    // array.concat()生成array的副本,sort排序不改变array原数组;使用concat为浅拷贝
    return array.concat().sort().filter(function(item, index, array){
        // 如果是第一个元素或者相邻的元素不相同
        return !index || item !== array[index - 1]
    })
}

console.log(unique(array)); // [1, '1', 2]

利用 for/forEach/filter()和 indexOf()

indexOf 底层还是使用 === 进行判断, NaN === NaN的结果为 false,所以使用 indexOf 查找不到 NaN 元素
 

var arr = [1, 2, NaN];
arr.indexOf(NaN); // -1

for+indexOf

var res = [];
for (var i = 0; i < arr.length; i++) {
  if (res.indexOf(arr[i]) == -1) {
    res.push(arr[i]);
  }
}
console.log(res); 

forEach+indexOf


var res = [];
arr.forEach(function(item, index) {
  if (res.indexOf(item) == -1) {
    res.push(item);
  }
});
console.log(res); 

filter+indexOf


var res = arr.filter(function(item, index) {
  return arr.indexOf(item) == index;
});
console.log(res); 

ES6 的 new Set()实现去重

var arr = [1, 6, 4, 6, 6, 4, 2, "a", "a"];
//第一种
var newarr = Array.from(new Set(arr));
console.log(newarr); //[1, 6, 4, 2, "a"]
//第二种
var newarr1 = [...new Set(arr)];
console.log(newarr1); //[1, 6, 4, 2, "a"]

set可以对NaN去重

function unique(array) {
   return Array.from(new Set(array));
}
console.log(unique([NaN, NaN])) // [NaN]

ES6 的 includes 实现去重

var arr = [1, 6, 4, 6, 6, 4, 2, "a", "a"];
var res = [];
arr.forEach(function(item, index) {
  if (!res.includes(item)) {
    res.push(item);
  }
});
console.log(res); //[1, 6, 4, 2, "a"]

利用对象的属性去重

根据对象的属性不能相同的特点进行去重

var arr = [1, 1, '1', '1', true, true,'true', 'true', 15, 15, false, false, undefined, undefined, null, null, 'NaN',  NaN, NaN,0, 0, 'a', 'a', {}, {}]
var res = [];
var obj = {};
for (var i = 0; i < arr.length; i++) {
  if (!obj[arr[i]]) { //对象没找到该属性返回undefined
    obj[arr[i]] = true;
    res.push(arr[i]);
  }
}
console.log(res); // 此方法 1 和 '1'会判断为同一个值,因为对象的键值只能是字符串
// [1, true, 15, false, undefined, null, 'NaN', 0, 'a', {…}]

 利用hasOwnProperty

对象的键值只能是字符串,1和'1'会判断为同一个值。可以使用 typeof item + item 拼成字符串作为 key 值来避免这个问题。

function unique(arr) {
    var obj = {};
    return arr.filter(function(item, index, arr){
        return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}] 全部去重了

但依然无法正确区分出两个对象,如 {value: 1} 和 {value: 2},因为 typeof item + item 的结果都会是 object[object Object],可以使用 JSON.stringify 将对象序列化:

var array = [{value: 1}, {value: 1}, {value: 2}];

function unique(array) {
    var obj = {};
    return array.filter(function(item, index, array){
        console.log(typeof item + JSON.stringify(item))
        return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true)
    })
}

console.log(unique(array)); // [{value: 1}, {value: 2}]

但以上方法仍无法处理正则对象去重, JSON.stringify 任何一个正则表达式的结果都是 {}

如/a/和/b/会被判断为同一值,解决方法:判断是正则的情况

item = item instanceof RegExp ? item.toString() : item
var array = [/a/, /a/, /b/, "1", 1, new String('1'), 1, new String('1'), NaN, NaN, null, undefined];

function unique(array) {
    var obj = {};
    return array.filter(function(item, index, array){
        item = item instanceof RegExp ? item.toString() : item;
        return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true)
    })
}
console.log(unique(array)) 
// [/a/, /b/, '1', 1, String, NaN, null, undefined]

利用map实现去重

let map = new Map()
let newArr = []
arr.forEach(ele => {
    if (!map.has(ele)) {
        map.set(ele, 1)
        newArr.push(ele)
    }
});

map+filter

function unique (arr) {
    const map = new Map()
    return arr.filter((a) => !map.has(a) && map.set(a, 1))
}

利用reduce实现去重

let res = (arr) =>{
    let newArr = []
    arr.reduce((pre, next)=>{
      if(!pre.get(next)){
        pre.set(next, 1)
        newArr.push(next)
      }
      return pre
    },new Map())
    return newArr.sort((a, b) => {
        return a - b
    })
}
console.log(res(arr))

利用reduce+includes

function unique(arr){
    return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr));
// [1, 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}]
// {}未去重

for...of + includes() 合并去重

function distinct(a, b) {
    let arr = a.concat(b)
    let result = []
    for (let i of arr) {
        !result.includes(i) && result.push(i)
    }
    return result
}

利用递归

var arr = [3, 4, 5, 2, 3, 1, 1, 2];
        function unique(arr){
            var newArr = arr;
            
            //先排序
            newArr.sort((a,b) => {
                return a - b;
            });
            function loop(index){
                if (index >= 1) {
                    if (newArr[index] === newArr[index-1]) {
                        newArr.splice(index,1);//有相等的 则删除后一个
                    }
                    loop(index-1);//递归
                }
            }
            loop(newArr.length-1);
            return newArr
        }
        console.log(unique(arr));

注意

NaN、undefined、null及{}、正则等对象的去重需要特别处理

NaN==NaN为false / NaN===NaN为false

{} 和 正则对象 使用==和===也都为false

console.log(null == null); // true
console.log(null === null); // true

console.log(undefined == undefined); // true
console.log(undefined === undefined); // true

console.log(null == undefined); // true
console.log(null === undefined); // false
var str1 = '1';
var str2 = new String('1');
console.log(str1 == str2); // true
console.log(str1 === str2); // false

对于数组

var array = [1, 1, '1', '1', null, null, undefined, undefined, new String('1'), new String('1'), /a/, /a/, NaN, NaN];

各方法的去重情况:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值