题外话:今天周六openDay,日常上班,上午做做题,下午看看TS,安排的满满当当。
前天 Kill Eve Season3 完结。好像大家都比较喜欢最后小变态说的那句:Now we walk, and we never look back...
其实我比较喜欢前面那段,有点小浪漫:When I try and think of my future. I just ...See your face over and over again...
不甜吗!!!!早上广播里《人文通识》讲的是杜月笙,今晚回去复习一下《教父》。
数组去重
数组操作老生常谈,leeCode上一道题目解法无数,有时候写了几十行发现人家只写了几行简直要被自己的蠢死。
来一个数组,能有几种去重方法呢。
var arr = [1, 2, 3, 2, '2', '2', '3', 1];
1.双层循环
此方法虽然老旧,比不上一些新函数操作方便,但是重点是 兼容性好!
function unique(arr){
var res = [];
for (var i = 0, len = arr.length; i < len; i++) {
for (var j = 0, resLen = res.length; j < resLen; j++) {
if (arr[i] === res[j]) { // 如果res数组中包含arr[i] 跳出res数组的循环 看arr的i+1项
break;
}
}
if (j === resLen) { // res循环到最后没有arr[i] 就加进去
res.push(arr[i]);
}
}
return res;
}
2. indexOf()
思路同1,简化了一层循环。
function unique(arr){
var res = [];
for (var i = 0, len = arr.length; i < len; i++) {
var cur = arr[i];
if(res.indexOf(cur) === -1) { // res中不包含cur
res.push(cur);
}
}
return res;
}
3.排序后去重
用到 sort(),注意两点:
1. sort() 在原数组上进行排序,不生成副本。
2.调用 sort()方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。
var arr = [1, 11, 3, 35, 4, 13];
arr.sort(); // => [1, 11, 13, 3, 35, 4]
arr.sort((a, b) => a - b); // => [1, 3, 4, 11, 13, 35]
arr.sort((a, b) => b - a); // => [35, 13, 11, 4, 3, 1]
function unique(arr){
var res = [];
var sortArr = arr.concat().sort(); // 复制数组且排序
var cur;
for(var i = 0, len = sortArr.length; i < len; i++) {
if (!i || cur !== sortArr[i]) {
res.push(sortArr[i]);
}
cur = sortArr[i];
}
return res;
}
4.filter()
ES 5 的 filter() 方法,注意两点:
1. 不操作原数组,返回一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
2. 不会对空数组进行检查。
function unique(arr){
var res = arr.filter((item, index, arr) => {
return arr.indexOf(item) === index;
// indexOf()返回某个指定的字符串值在字符串中首次出现的位置。
})
return res;
}
5. reduce()
function unique(arr) {
return arr.reduce((pre, cur) => pre.includes(cur) ? pre : [...pre, cur], []);
}
6.ES6 数据结构Set
ES6提供了 数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。
function unique(arr) {
return Array.from(new Set(arr)); // new Set() 出来是个对象
}
function unique(arr) {
return [...new Set(arr)];
}
7.ES6 数据结构Map
ES6提供了 数据结构Map。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
function unique(arr){
var res = new Map()
return arr.filter(item => !res.has(item) && res.set(item, 1));
}
---------------去重结束分割线-----别问第8种-----问就继续看-----------------------
特殊类型比较
以上几种方法对于特殊类型有不同表现,下面来对比一下。
var str1 = '1';
var str2 = new String('1');
str1 == str2; // true
str1 === str2; // false
null == null; // true
null === null; // true
undefined == undefined; // true
undefined === undefined; // true
NaN == NaN; // false
NaN === NaN; // false
/a/ == /a/; // false
/a/ === /a/; // false
{} == {}; // false
{} === {}; // false
对于下列数组,上述7种方法的运行结果是什么捏,列个表看看吧。
var arr = [1, 1, '1', '1', null, null, undefined, undefined, new String('1'), new String('1'), /a/, /a/, NaN, NaN];
方法 | 运行结果 | 说明 |
---|---|---|
1.双层循环 | [1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN] | 对象和 NaN 不去重 |
2.indexOf() | [1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN] | 对象和 NaN 不去重 |
3.sort()后循环 | [/a/, /a/, 1, "1", String, String, NaN, NaN, null, undefined] | 对象和 NaN 不去重 |
4.filter() | [1, "1", null, undefined, String, String, /a/, /a/] | 对象不去重, NaN 会被忽略掉 |
5.reduce() | [1, "1", null, undefined, String, String, /a/, /a/, NaN] | 对象不去重 |
6.Set数据结构 | [1, "1", null, undefined, String, String, /a/, /a/, NaN] | 对象不去重 |
7.Map数据结构 | [1, "1", null, undefined, String, String, /a/, /a/, NaN] | 对象不去重 |
8.Object键值对 | [1, "1", null, undefined, String, /a/, NaN] | 欧开 |
哎呀,居然没有一种方法能完全去重,最后加个终极方法吧。
8.Object 键值对
hasOwnProperty()中区分不了string or number,所以用typeof + JSON.stringify()来表示唯一性。
function unique(arr){
var obj = {};
return arr.filter((item, index, arr) => {
return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true);
})
}