一只菜鸟攻城狮啊

一只菜鸟攻城狮啊

其实数组去重的实现就分为两大类

  • 利用语法自身键不可重复性
  • 利用循环(递归)和数组方法使用不同的api来处理。

注意⚠️:下列封装成方法的要在函数开始增加类型检测,为了让去重的实现代码更加简单易懂,封装时我会省略类型检测

function noRepeat(){
    if (!Array.isArray(arr)) {
    console.log('type error!')
    return
  }
  // XXX执行代码
}

利用键不可重复性

Set

原理:利用set存储的数据没有重复,结果为对象,需要再转换成数组

// 方法一
var arr = [1,1,2,1,3,4,5];
var set = new Set(arr);
console.log(Array.from(set))
// 方法二
[...new Set(arr)];

利用对象的属性

原理:利用对象的属性唯一(速度快,占空间多,用空间来换时间)

var res = [];
var obj = {};
for(var i=0; i<arr.length; i++){
  if(!obj[arr[i]] ){
    obj[arr[i]] = 1;
    res.push(arr[i]);
  }
}

Map

原理:利用map对象不重复,思路和对象属性一致。

function arrayNonRepeatfy(arr) {
  let map = new Map();
  let array = new Array();  // 数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if(map .has(arr[i])) {  // 如果有该key值
      map .set(arr[i], true);
    } else {
      map .set(arr[i], false);   // 如果没有该key值
      array .push(arr[i]);
    }
  }
  return array ;
}

利用数组下标不能重复(仅适用纯数字数组)

原理:利用数组下标不能重复。

function norepeat(arr){
  var newArr = [];
  var arrs = [];
  for(var i=0;i<arr.length;i++){
    var a = arr[i];
    newArr[a] = 1;
  }
  for(var i in newArr){
    arrs[arrs.length] = i;
    console.log(i);
  }
}

利用循环(递归)和数组方法使用不同的api

indexOf()

原理:利用indexOf检测新数组是否有当前元素,没有则添加。

方式一 检测新数组是否有当前元素
function norepeat(arr){
  var newarr = [];
  for(var i in arr) {
      if(newarr.indexOf(arr[i]) == -1){
          newarr.push(arr[i]);
      }
  }
  return newarr;
}

方式二 检测当前元素第一次出现的位置和当前位置是否相等,相等则添加
function norepeat(arr){
  var newarr = [arr[0]];  //默认加入第一个数  因为第一个数没比较的必要
    for(var i =1;i<arr.length;i++){
        if(arr.indexOf(arr[i])==i){
            newarr.push(arr[i])
        }
    }
  return newarr;
}

方式三 filter和indexOf
function unique(arr) {
  return arr.filter(function(item, index, arr) {
    //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
    return arr.indexOf(item, 0) === index;
  });
}

includes()

原理:利用includes检测新数组中是否含有当前元素,没有则添加

方式一 利用普通for循环和includes
function norepeat(arr) {
  var newarr =[];
  for(var i = 0; i < arr.length; i++) {
   if(!newarr.includes(arr[i])) { //includes 检测数组是否有某个值
      newarr.push(arr[i]);
    }
  }
  return array
}

方式二 利用reduce和includes
function norepeat(arr){
    return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}

注意⚠️:indexOf和includes均可以和for循环,reduce配合使用

sort()

原理:先利用sort排序再比较相邻的是否相等

// 方法一 检测相邻相等则添加到新数组
function norepeat(arr) {
  arr = arr.sort()
  var arrry= [arr[0]];
  for(var i = 1; i < arr.length; i++) {
    if(arr[i] !== arr[i-1]) {
      arrry.push(arr[i]);
    }
  }
  return arrry;
}

// 方式二 在原数组上检测,相邻元素相同则删除
function norepeat(arr) {
  arr.sort(function (a, b) { return a - b; });
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] == arr[i + 1]) {
      arr.splice(i, 1);
      i--;
    }
  }
  return arr;
}

递归

原理:借用递归比较 index和index-1位是否相同,相同则删除

function noRepeat(arr) {
  // 获取长度
  var len = arr.length;
  //对数组进行排序才能方便比较
  arr.sort(function (a, b) {
   return a - b;
  })
  // 用递归的方法进行去重
  function loop(index) {
    if (index >= 1) {
      if (arr[index] === arr[index - 1]) {
        arr.splice(index, 1);
      }
      loop(index - 1); //递归loop函数进行去重
    }
  }
  loop(len - 1);
  return arr;
};
09-10 10:29