1. 程式人生 > >JS數組專題2?? ? 數組去重

JS數組專題2?? ? 數組去重

com prev includes 跳過 lag 技術 初始 -- each

距離上次發文,已經有一段時間了,最近工作比較忙,這不眼看快雙十一了,就相當於給大家一些福利吧!

技術分享圖片

一、什麽是數組去重

簡單說就是把數組中重復的項刪除掉,你 GET 到了嗎 ?下面我將簡單介紹下幾種基本的方法及其優缺點。

二、方法匯總

  • 兩層循環

** 無相同值直接 push 進新數組,有相同的值則直接跳過本次內部循環 **

/*
 * @param {Array} arr    -要去重的數組
 * @param {Array} result -初始化結果數組
 */
const unique = (arr, result = []) => {
  const len = arr.length;
  for (let i = 0; i < len; i++) {
    for (let j = i + 1; j < len; j++) {
      if (arr[i] === arr[j]) {
        // 相等則直接跳過
        j = ++i;
      }
    }
    result.push(arr[i]);
  }
  return result;
}

** 相同的做標記,與新數組作比較,沒有則插入 **

/*
 * @param {Array} arr    -要去重的數組
 * @param {Array} result -初始化結果數組
 */
const unique = (arr, result = []) => {
  result.push(arr[0]);
  const len = arr.length;
  let rLen = result.length;

  for (let i = 1; i < len; i++) {
    let flag = false;
    for (var j = 0; j < rLen; j++) {
      if (arr[i] === result[j]) {
        flag = true;
        break;
      }
    }
    if (!flag) {
      rLen++;
      result.push(arr[i]);
    }
  }
  return result;
}

** 原地算法(在數組本身操作) **

const unique = arr => {
  const len = arr.length;
  for (let i = 0; i < len; i++) {
    for (let j = i + 1; j < len; j++) {
      if (arr[i] == arr[j]) {
        arr.splice(j,1);
        len--;
        j--;
      }
    }
  }
  return arr;
};

看似代碼代碼簡單,實則內存占用高,不實用

  • 單層循環

** 對象鍵不能重復 **

const unique = (arr, result = []) => {
  const obj = {};
  const len = arr.length;
  for (let i = 0; i< len; i++) {
    if (!obj[arr[i]]) {
      // 鍵沒有,則添加
      obj[arr[i]] = 1;
      result.push(arr[i]);
    }
  }
  return result;
};

這種方法無法判斷 ‘1‘1 等類型,解決方案:

  1. 添加判斷數據類型,比如 typeofobj[typeof arr[i] + arr[i]] 不過這還是判斷不了 [‘1‘][1],因為這被相加後,結果都一樣
  2. 添加 JSON.stringify() 對結果進行去格式化,這時就可以判斷了

** 排序後比較前後兩位,不相等則添加進新數組 **

const unique = (arr, result = []) => {
  arr.sort();
  result.push(arr[0]);
  const len = arr.length;
  let rLen = result.length;
  for (let i = 1; i < len; i++) {
    if (arr[i] !== result[rLen - 1]) {
      result.push(arr[i]);
      rLen++;
    }
  }
  return result;
}

方法比較直接

** 原地算法(排序後比較前後兩位,相等則刪除) **

const unique = (arr) => {
  arr.sort();
  let len = arr.length;
  for (let i = 1; i < len; i++) {
    if (arr[i] === arr[i - 1]) {
      arr.splice(i, 1)
      len--;
    }
  }
  return arr;
}

不消耗額外的空間

  • 偷懶的節奏

** indexOf 判斷數組元素第一次出現的位置是否相同 **

const unique = (arr, result) => {
  arr.forEach((item, index, array) => {
    if(array.indexOf(item) === index) {
      result.push(item);
    }
  });
  return result;
}

// 使用ES6 filter
const unique = (arr) =>
  arr.filter((item, index) =>  array.indexOf(item) === index);

使用ES6 方法更簡潔性能更好

** indexOf 的ES6 方法通過 includes 判斷新數組中是否有該元素 **

const unique = (arr, result) => {
  arr.forEach((item, index, array) => {
    if(!result.includes(item)) {
      // 或者 result.indexOf(item) === -1
      result.push(item);
    }
  });
  return result;
}

建議使用 includes

** Map 數據結構,不懂 Map 的自行解決,傳送門 **

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

對象關系映射可以設置不同類型的鍵,使之很快能收集 arr 中不一樣的數據

** Set 數據結構,不允許出現重復數據,而且 Set 支持解構 傳送門 **

const unique = arr => Array.from(new Set(arr));

// 或者通過 ES6 的 ...解構
const unique = arr => [...new Set(arr)];

簡單粗暴

** reduce,給定初始值,根據數組循環給出最終值 **

const unique = (arr, result = []) => arr.reduce((prev,curr) => prev.includes(curr) ? prev : [...prev, curr], result);

三、總結

方法已經說了差不多了,就看你怎麽用了,其中有一些差不多的方法,只是給了說明,沒給具體的例子,希望大家自己去試一下,告辭!

JS數組專題2?? ? 數組去重