数组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的话,用对象的处理方式更易理解,简单,高效。

posted on 2016-06-13 16:22  hobbycc  阅读(224)  评论(0编辑  收藏  举报

导航