Array内置对象的属性
数组方法:
sort(): arrayObject.sort(sortby);
sortby可选,规定排序顺序,但是必须是函数。sort() 方法用于对数组的元素进行排序。
如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序,A在a之前。
要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
实际生产中,受限于服务器成本等因素,当单次数据查询成为整体性能瓶颈时,也会考虑通过将排序在前端完成的方式来优化性能。
function sortBy(a,b) { return a - b ;// 正序 }
reverse():arrayObject.reverse()方法用于颠倒数组中元素的顺序。arrayObject.reverse(),该方法会改变原来的数组,而不会创建新的数组。
var arrs = [1,2,3,4]; console.log(arrs.reverse()); //[4,3,2,1]
splice(): splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目组成的数组,该方法会改变原始数组。
arrayObject.splice(index,howmany,item1,.....,itemX); //实例如下 var arr = new Array(6) arr[0] = "George" arr[1] = "John" arr[2] = "Thomas" arr[3] = "James" arr[4] = "Adrew" arr[5] = "Martin" var del = arr.splice(2,3,"William") del //["Thomas", "James", "Adrew"] arr //["George", "John", "William", "Martin"]
toString(): 将数组转换为一个字符串,并且返回这个字符串;这个字符串默认以","进行分割。
var arrs = [1,2]; console.log(arrs.toString()); // 1,2
slice(): arrs.slice(start,end);从数组中截取一段,并返回。
start参数【必须】从何处开始选取(包括start),如果是负数,那么会从尾部选取,比如-1代表最后一个元素,-2代表倒数第二个元素,以此类推。
End参数【可选】规定是从何处结束选取(不包括end),如果没有指定该参数,那么数组会包含从start开始到数组结束的所有元素,如果该参数是负数的话,那么它规定的是从数组尾部开始算起的元素。
reduce(),归并方法:前向归并与
reduceRight(),后项归并
这两个的主要区别是从哪头开始遍历,迭代次数为ar.length - 1
var values = [1,2,3,4,5,6]; var i = 1; var sum = values.reduce(function(prev,cur,index,array){ console.log("prev " + parseInt(prev)); console.log("cur " + parseInt(cur)); console.log("迭代次数 " + i++) return prev + cur; }); console.log(sum); //输出结果 prev 1 cur 2 迭代次数 1 prev 3 cur 3 迭代次数 2 prev 6 cur 4 迭代次数 3 prev 10 cur 5 迭代次数 4 prev 15 cur 6 迭代次数 5 21
var values = [1,2,3,4,5,6]; var i = 1; var sum = values.reduceRight(function(prev,cur,index,array){ console.log("prev " + parseInt(prev)); console.log("cur " + parseInt(cur)); console.log("迭代次数 " + i++) return prev + cur; }); console.log(sum); //输出结果 // prev 6 cur 5 迭代次数 1 prev 11 cur 4 迭代次数 2 prev 15 cur 3 迭代次数 3 prev 18 cur 2 迭代次数 4 prev 20 cur 1 迭代次数 5 21
数组判断:
使用typeof不能测出来,因为数组是返回"object"的。
//方法1 自带的isArray方法,需要考虑IE8- var array6 = []; Array.isArray(array6 );//true //方法2 利用instanceof运算符,某些IE版本不兼容 var array5 = []; array5 instanceof Array;//true
//方法3 能力检测,测试是否具有数组的一些方法,如slice();
array.slice
//方法4 利用toString的返回值,最好的方法 function isArray(o) { return Object.prototype.toString.call(o) === ‘[object Array]‘; }
常见的数组问题:
1、数组高效去重
原理:新建一新数组,遍历传入数组,值不在新数组就加入该新数组中;
注意点:判断值是否在数组的方法“indexOf”是ECMAScript5 方法,IE8以下不支持,需多写一些兼容低版本浏览器代码。
// 最简单数组去重法1 function unique(array){ var n = []; //一个新的临时数组 //遍历当前数组 for(var i = 0; i < array.length; i++){ //如果当前数组的第i已经保存进了临时数组,那么跳过, //否则把当前项push到临时数组里面 if (n.indexOf(array[i]) == -1) n.push(array[i]); } return n; }
// 借助于Set对象与...方法
[...new Set(arr)]
2、数组顺序扰乱
原理:每次从元数组中抽取一个,然后添加到新数组中,并在原数组中删除。
注意点:arrayObject.splice(index,howmany,item1,.....,itemX) : splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目(这里是一个数组)。该方法会改变原始数组。item是向数组中添加的新元素。
delete删除可以对数组和对象进行元素的删除,数组删除之后,使用Undefined来填补。对象就是删除属性的值(没有了)。
//每次随机抽一个数并移动到新数组中 function shuffle(array) { var copy = [], n = array.length, i; // 如果还剩有元素则继续。。。 while (n) { // 随机抽取一个元素 i = Math.floor(Math.random() * array.length); // 如果这个元素之前没有被选中过。。 if (i in array) { copy.push(array[i]); delete array[i]; n--; } } console.log(array); console.log(copy); return copy; } shuffle([2,5,6,9,8,5]);
这样本来的数组也被改变了,变为空。如果在进入函数的时候把array赋值给另一个变量也是不可行的,因为数组的访问也是按引用的,除非深度复制一份副本(for循环)。不然使用delete||splice就会改变原来的数组。
3、数组求交集
原理:利用filter()方法,返回满足条件的值组成的数组。
相同使用方法的方法如下:
every():每项都(满足要求)为真则为真。
filter():返回为真的项组成的数组。
forEach():每一项都执行给定函数的操作,没有返回值。
map():执行函数操作,返回操作的返回值组成的数组。
some():任意项为真则为真。
以下是公用的模版形式:
var result = ArrObj.func(function(item,index,ArrObj){ return (item >2);//条件 });
//利用filter和数组自带的indexOf方法 array1.filter(function(n) { return array2.indexOf(n) != -1 });
4、数组求并集
原理:连接连个数组并去重
注意:concat():concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。arrayObject.concat(arrayX,arrayX,......,arrayX)
function unique(arr1,arr2){ var a = arr1.concat(arr2),result = []; for (var i = 0,len = a.length;i<len;i++){ if(result.indexOf(a[i]) == -1){ result.push(a[i]); } } return result; } unique([2,5,6,5,6,8],[5,8,9,2]);
5、数组去重的实现
1、基本数组去重
原理:新建一个数组并返回,把原数组的元素在新建数组中没有存在的添加到新数组中。
Array.prototype.unique = function(){ var result = []; this.forEach(function(v){ if(result.indexOf(v) < 0){ result.push(v); } }); return result; }
2、利用hash表去重,这是一种空间换时间的方法,这里如果存在元素是引用类型的就会出问题的
原理:借助于一个对象来进行判断是否唯一
Array.prototype.unique = function(){ var result = [],hash = {}; this.forEach(function(v){ if(!hash[v]){ hash[v] = true; result.push(v); } }); return result; }
上面的方法存在一个bug,对于数组[1,2,'1','2',3],去重结果为[1,2,3],原因在于对象对属性索引时会进行强制类型转换,arr[‘1’]和arr[1]得到的都是arr[1]的值,因此需做一些改变:
Array.prototype.unique = function(){ var result = [],hash = {}; this.forEach(function(v){ var type = typeof(v); //获取元素类型 hash[v] || (hash[v] = new Array()); if(hash[v].indexOf(type) < 0){ hash[v].push(type); //存储类型 result.push(v); } }); return result; }
3、先排序后去重
Array.prototype.unique = function(){ this.sort(); var result = this; result.forEach(function(v,i){ if(v === result[i+1]){ result.splice(i,1); } }); return result; } [1,2,5,6,4,"1",2].unique(); function randomArr(num,min,max){ var result = []; while(num--){ result.push(Math.floor(Math.random()*(max-min)) + min +1); } return result; } var arr = randomArr(20000,1,20000); console.log(arr.unique());
6、快速排序的实现
方法一(尽可能不用js数组方法):
function quickSort(arr){ qSort(arr,0,arr.length - 1); } function qSort(arr,low,high){ if(low < high){ var partKey = partition(arr,low,high); qSort(arr,low, partKey - 1); qSort(arr,partKey + 1,high); } } function partition(arr,low,high){ var key = arr[low]; //使用第一个元素作为分类依据 while(low < high){ while(low < high && arr[high] >= arr[key]) high--; arr[low] = arr[high]; while(low < high && arr[low] <= arr[key]) low++; arr[high] = arr[low]; } arr[low] = key; return low; }
方法二(使用js数组方法):
function quickSort(arr){ if(arr.length <= 1) return arr; var index = Math.floor(arr.length/2); var key = arr.splice(index,1)[0]; var left = [],right = []; arr.forEach(function(v){ v <= key ? left.push(v) : right.push(v); }); return quickSort(left).concat([key],quickSort(right)); }
另外要知道,快速排序的平均时间复杂度O(nlogn),最坏情况是有序的情况,时间复杂度为n的平方,另外快速排序是不稳定的。
7、生成一个二维或者多维的数组,使用for循环来赋值
function to2Arr(x,y,r){ var resArr = new Array(y); var sArr = new Array(x); for (var i = 0; i < x; i++){ sArr[i] = r; } for (var j = 0; j < y; j++){ resArr[j] = sArr; } console.log(resArr); return resArr; } to2Arr(5,5,1);//行数、列数、初始值
如下的三维数组:
function to3Arr(x,y,z,r){ var resArr = new Array(y); var sArr = new Array(x); var res3deg = new Array(z); for (var i = 0; i < x; i++){ sArr[i] = r; } for (var j = 0; j < y; j++){ resArr[j] = sArr; } for(var k = 0;k < z; k++){ res3deg[k] = resArr; } console.log(resArr); console.log(res3deg); return res3deg; } to3Arr(5,5,5,1);
如下生成一个数组乘积的二维数组:
function fn(n,arr){ var arr2deg = new Array(); for(var i=0;i<n;i++){ arr2deg[i] = new Array(); for(var j=0;j<n;j++){ arr2deg[i][j] = arr[i]*arr[j]; } } return arr2deg; } fn(4,[1,2,3,4]);
8、对数组进行循环的时候,如果不知道需要循环几次就把for方法放在一个函数中,然后使用for来调用
如下这般:
function func(n,arr,m,maxlen){ var res = arr; for(var i=0;i<m;i++){ _do(res,maxlen); } function _do(arrCur,maxlen){ for(var j=0;j<n;j++){ for(var k=0,len=arrCur.length;k<len;k++){ if(k-j<=maxlen && j-k<=maxlen){ res.push(arr[j]*arrCur[k]); } } } console.log(res); res = res.slice(len); console.log(res) } function getMax(arrays){ //获取数组最大值 return arrays.reduce(function(pre,cur,index,array){ return Math.max(pre,cur); }); } return getMax(res); } func(7,[2,3,40,5,6,-8,9],3,4);