在面试中,我们常常会遇到数组去重的问题,这里整理一下。
双重循环去重
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function uniq(array) { let res = []; for (var i = 0; i < array.length; i++) { for (var j = 0, len = res.length; j < len; j++) { if (array[i] === res[j]) { break; } } if (j === len) res.push(array[i]); } return res; }
var arr = [1, 2, 1, "3", "2", "1"]; console.log(uniq(arr));
|
双循环去重优化
思路:获取没重复的最右一值放入新数组(判断值得右侧有无重复)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
function uniq(array) { var res = [], len = array.length; for (var i = 0; i < len; i++) { for (var j = i + 1; j < len; j++) { if (array[i] === array[j]) { i++; j = i; } } res.push(array[i]); } return res; }
|
IndexOf
利用 IndexOf 简化内层循环:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
function uniq(array) { let res = []; for (var i = 0; i < array.length; i++) { if (res.indexOf(array[i]) === -1) { res.push(array[i]); } } return res; }
|
排序后相邻去除法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
function uniq(array) { array.sort(); let res = [array[0]]; for (var i = 1; i < array.length; i++) { if (array[i] !== array[i - 1]) { res.push(array[i]); } } return res; }
|
对象键值去重
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
function uniq(array) { var res = [], temp = {}; array.forEach((val) => { let type = typeof val; if (!temp[val]) { temp[val] = [type]; res.push(val); } else if (temp[val].indexOf(type) < 0) { temp[val].push(type); res.push(val); } }); return res; }
|
数组下标法
1 2 3 4 5 6 7 8 9 10 11 12 13
|
function uniq(array) { var res = []; array.forEach((v, i) => { if (array.indexOf(v) === i) { res.push(v); } }); return res; }
|
filter
ES5 提供了 filter 方法,我们可以用来简化外层循环
1 2 3 4 5 6
| function unique(array) { var res = array.filter(function (item, index, array) { return array.indexOf(item) === index; }); return res; }
|
利用 ES6 的 set
1 2 3 4 5 6 7 8
| function uniq(arr) { return Array.from(new Set(arr)); }
function unique(array) { return [...new Set(array)]; }
|
写在最后
去重的方式有很多,我们需要知道在合适的场景要选择合适的方法,这样才能达到最优。