JS陣列去重的實現

一隻菜鳥攻城獅啊發表於2020-09-09

其實陣列去重的實現就分為兩大類

  • 利用語法自身鍵不可重複性
  • 利用迴圈(遞迴)和陣列方法使用不同的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;
};

相關文章