数组unique
初探js数组去重,我是这样写的:
方法一
function unique(arr){ var hash = {}, res = []; for(var i=0,len=arr.length;i<len;i++){ var key = arr[i]; if(!hash[key]){ hash[key] = true; res.push(key); } } return res; }
定义一个数组,试试看:
var arr = [0,"0",1,0,"a","b"]; var newArr = unique(arr); alert(newArr);
输出:0,1,a,b
显然这不符合我们要求,因为0与字符串0是两个概念。但上述写法用于对付”单纯“数组还是可以的。
方法二
function unique(arr){ var item, res = []; for(var i=0,len=arr.length;i<len;i++){ for(var j=i+1;j<len;j++){ if(arr[i] === arr[j]){ i++; } } res.push(arr[i]); } return res; };
输出:0,1,0,a,b
不错,符合我们的要求。
该方法思想是在原数组中对相邻两个元素进行比较,如果相等,让外层for循环 i 变量递增一次,先不用放进结果数组中,因为,反正还有相同的元素嘛!如果一次循环下来没有发现与之相等的元素,再把该元素放进结果数组中也不迟。
方法三
function unique(arr){ var res = []; for(var i = 0,len = arr.length;i<len;i++){ for(var j = 0,jLen = res.length;j<jLen;j++){ if(arr[i] === res[j]){ break; } } if(j === jLen){ res.push(arr[i]); } } return res; };
输出:0,0,1,a,b
该方法思想是每次在原数组中取出一个元素,与结果数组中的元素进行一一比较,如果两元素相等,就不放进结果数组,当结果数组循环完毕都没发现与之相等,再把它放进结果数组中,这时的 j 必等于 jLen。
方法四
function unique(arr){ var res = [], item; for(var i = 0,len = arr.length;i<len;i++){ item = arr[i]; if(res.indexOf(item) === -1){ res.push(item); } } return res; };
输出:0,0,1,a,b
这样的写法与法三思想是一致的,只不过判断条件采用的是ES5的 indexOf 方法。
进阶
针对方法一,可以用 filter 做简化
function unique(arr){ var hash = {}; return arr.filter(function(item){ return hash.hasOwnProperty(item)?false:(hash[item]=true); }); };
由于Object里key为string类型,我们不能对0与“0”作区分,因此我们可以再Object中key上下功夫,也就是把数据类型也存入key。
function unique(arr){ var res = [], hash = {}; for(var i = 0,len = arr.length;i<len;i++){ var item = arr[i], key = typeof (item)+item; if(!hash[key]){ res.push(item); hash[key] = true; } } return res; };
参阅其他资料,还有以下更为高级的写法:
function unique(arr){ return arr.sort().filter(function(item,pos,ary){ return !pos||item!=ary[pos-1]; }); };
该方法是先对目标数组进行一个排序,然后再调用 ES5 中数组的 filter 方法进行条件过滤。但输出结果与方法一相同,不能对0与字串0作区分。
ES6写法
function unique(arr){ return Array.from(new Set(arr)); };
如果你要对诸如这样的数组去重[{a:1},{a:2},{a:1}],目前我还没有对应的解决方案,不过在实际开发过程中,还没遇到对json对象去重过,如果是要做的话,你可能会说不就是多判断几下对象的属性、属性个数与属性值嘛!倘若属性值仍然是一个对象呢,真是不敢想象!
结语
个人认为,不考虑ES56的话,用对象的处理方式更易理解,简单,高效。