learn icon indicating copy to clipboard operation
learn copied to clipboard

JavaScript专题之数组去重

Open yangtao2o opened this issue 4 years ago • 0 comments

数组去重,老生常谈,把学习到的多种方式进行归纳总结

双层循环

第一种:

function unique(arr) {
  var result = [];
  for (var i = 0, arrLen = arr.length; i < arrLen; i++) {
    for (var j = 0, resLen = result.length; j < resLen; j++) {
      if (arr[i] === result[j]) {
        break;
      }
    }
    if (j === result.length) {
      result.push(arr[i]);
    }
  }
  return result;
}

第二种:

function unique(arr) {
  let arrary = [].concat(arr); // 避免修改原数组,存个副本
  for (let i = 0, len = arrary.length; i < len; i++) {
    for (let j = i + 1; j < len; j++) {
      if (arrary[i] === arrary[j]) {
        arrary.splice(j, 1); // splice() 修改原数组,所以需要手动修改长度
        len--;
        j--;
      }
    }
  }
  return arrary;
}

indexOf 方法

function unique(arr) {
  const result = [];
  for (let i = 0, len = arr.length; i < len; i++) {
    const current = arr[i];
    if (result.indexOf(current) === -1) {
      result.push(current);
    }
  }
  return result;
}

filter + indexOf 方法

function unique(arr) {
  let result = arr.filter(function(item, index, arr) {
    return arr.indexOf(item) === index;
  });
  return result;
}

// ES6
let unique = arr =>
  arr.filter((item, index, arr) => arr.indexOf(item) === index);

如果我们对一个已经排好序的数组去重,这种方法效率肯定高于使用 indexOf:

let unique = arr =>
  arr
    .concat()
    .sort()
    .filter((item, index, arr) => !index || item !== arr[index - 1]);

不过对于下面这种就会失效:

const arr = [2, 1, 1, 3, "1", 1, "1"];
//输出 [ 1, '1', 1, '1', 2, 3 ]

Object 键值对

利用一个空的 Object 对象,我们把数组的值存成 Object 的 key 值,比如 Object[value1] = true,在判断另一个值的时候,如果 Object[value2]存在的话,就说明该值是重复的。

let unique = arr => {
  const obj = {};
  return arr.filter(item =>
    obj.hasOwnProperty(typeof item + JSON.stringify(item))
      ? false
      : (obj[typeof item + JSON.stringify(item)] = true)
  );
};

注意:

  1. typeof item + item 是为了区分 1 还是 '1'
  2. typeof item + JSON.stringify(item) 是为了区分 {value: 1}, {value: 1}

如:

const arr = [1, "1", { value: 1 }, { value: 1 }];

let getObjType = arr => arr.map(item => typeof item + JSON.stringify(item));

getObjType(arr);

// ["number1", "string"1"", "object{"value":1}", "object{"value":1}"]

Set 集合 和 Map 集合

ES6 去重方式已经是非常的精简:

// Set
let unique = arr => Array.from(new Set(arr))

let unique = arr => [...new Set(arr)]

// Map
let unique = arr => {
  const seen = new Map();
  return arr.filter(item => !seen.has(item) && seen.set(item, true));
};

学习资料

yangtao2o avatar Apr 02 '20 14:04 yangtao2o