这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这篇文章主要介绍了 Javascript 中数组去重与拍平的相关资料,因为这是实际业务开发中经常遇到的,文中开始先进行了数组的判断介绍,因为在处理数组之前判断数据是不是数组很重要,有需要的朋友可以参考借鉴,下面来一起看看吧。
数组的判断
在说如何进行数组的去重和拍平之前,先说一下怎么判断数组,因为要进行数组的处理当然要先判断下传过来的数据是不是数组。
首先我们都知道 js 的数据类型只有 5 种,分别是 Undefined、Null、Boolean、Number 和 String,数组只是一个对象,用
返回的结果知识一个 Object 的字符串,因此我们需要通过其他手段来判断它,这里就说两种方法。
- typeof([])
第一种用 instenceof 方法
instanceof 是 ES5 提供的一个方法,它可以用来判断实例是否是某个类的实例,例如:
- [] instenceof Array
- //返回结果是true
这种方法的不好之处就是兼容性不好,对于一些低版本浏览器不支持 ES5 的就要懵逼了。
第二种方法是通过原型链的方式来判断
了解 js 的话都应该懂得 js 这个语言的特点就是原型链式的,所有的对象都继承自
, 而 prototype 上又有
- Object.prototype
方法,这个
- toString()
方法是干什么用的呢?就是以字符串的形式返回当前对象的值。第一次看可能这句话可能不大明白,举个例吧:
- toString()
- var num = 123;
- num.toString(); //返回结果为"123"
有没有看明白一点?就是返回 num 这个对象值的字符串形式,也就是 "123"。好了,这跟判断数组有什么关系?想一下所有的对象都继承自
,数组也是啊,如果把一个数组送到
- Object.prototype
里作为一个 "值",在调用
- Object.prototype
方法,那它应该显示出这个对象的名字才对啊,这就是判断的原理,代码如下:
- toString()
- Object.prototype.toString.call([]); //结果是"[object Array]"
像 jQuery 这样的脚本库的
用的就是这个方法。
- isArray()
数组拍平
说完判直奔主题,先是数组拍平,什么是数组拍平呢?就是把 [1,[2,[3,4],5]] 铺成[1,2,3,4,5]。关于数组拍平我有两种思路,第二种比较奇葩,留点悬念吧哈哈。
第一种是常规思路
对数组进行遍历,如果数组里面套着数组就继续遍历里面的,直到把每个元素都遍历完,然后一边遍历一边塞入新的数组变量里,这样就完成拍平了,具体代码如下:
- panelArr = function(arr) {
- var newArr = [];
- var isArray = function(obj) {
- return Object.prototype.toString.call(obj) === '[object Array]';
- };
- var dealArr = function(arr) {
- for (var i = 0; i < arr.length; i++) {
- isArray(arr[i]) ? dealArr(arr[i]) : newArr.push(arr[i]);
- }
- };
- dealArr(arr);
- return newArr;
- };
- console.log(panelArr([1, [2, 3]])); //[1,2,3]
当然这个方法也可以写在
里,使用起来更方便。这个方法有个问题就是内存占用上,因为采用递归如果数据量大了会占用大量大量内存。
- Array.prototype
第二种奇葩思路
第二种思路就是不把数组来看,也不遍历了直接拍平。听起来略奇怪,怎么能不遍历就拍平?就是使用
方法,将数组转换成字符串,然后正则去掉符号最后合并,这个方法在使用注意不能
- join()
, 因为如果这样分割的话,13 是 1 和 3 还是 13?不好区分,代码如下:
- join("")
- var arr = [1, 2, [33, 43], 20, 19];
- arr.join(".").replace(/,/g, ".").split("."); //["1", "2", "33", "43", "20", "19"]
注意:这个方法会转换数据类型成字符串。
数组去重
下面是数组去重,举例来说就是 [1,2,3,3,4,5,5,5,6] 变成[1,2,3,4,5,6]。这个实现的核心就是去重这里,如果能够快速判断元素是否重复就是关键。
还是两种思路
第一种遍历的思路
就是准备一个新的数组变量,塞入前每次对这个变量进行遍历看看是否有重复的,如果没有就塞入,最后生成的新数组就是去重后的数组了。示例代码如下:
- function uniqueArr(arr){
- var newArr = [];
- newArr.push(arr[0]);
- for(var i = 1; i<arr.length;i++){
- var repeat = false;
- for(var j = 0;j<newArr.length;j++){
- if(arr[i] == newArr[j]){
- repeat = true;
- }
- }
- if(!repeat){
- newArr.push(arr[i]);
- }
- }
- return newArr;
- }
第二种使用哈希判断
上面那个时间复杂度为
的方法并不是什么好方法,它的瓶颈就是判断是否重复这里,所以我们换成一个更高效的检索是否重复的方法,这个方法就是哈希,为什么哈希检索最快?翻翻数据结构吧,这里就不在赘述了。
- O(n^2)
这个方法的思路就是在原始数组和去重数组之间加入一个哈希过滤,总的来看就是原数组数据交给哈希,看是否有重复,若是没有则添加进去。具体代码如下:
- function uniqueArr(arr){
- var newArr = [],
- hashFilter = {};
- for(var i = 0;i<arr.length;i++){
- if(!hashFilter[arr[i]]){
- //若不存在将此属性对应的值改为true,并塞入去重数组中
- hashFilter[arr[i]] = true;
- newArr.push(arr[i]);
- }
- }
- return newArr;
- }
我青睐第二种,因为在判断是否重复这里真的很快,可以说是秒出。
总结
来源: http://www.phperz.com/article/17/0513/328084.html