[TOC] # 数组 ## **概念** &emsp;&emsp;将多个元素(通常是同一类型)按一定顺序排列放到一个集合中,那么这个集合就叫称之为做数组。 <br> ## **创建数组** &emsp;&emsp;创建数组也叫**定义数组**,定义一个数组变量跟定义一个基本类型的变量格式几乎一样。 &emsp;&emsp;定义数组语法格式: >[success]var 数组变量名 = 数组变量值; var 数组变量名 = [元素1,元素2,元素3……]; 元素与元素之间用英文逗号“ , ”隔开。 ``` //变量 // 创建一个空数组 var arr = []; // 创建一个数组,用于存储3个年龄,年龄分别为 20,30,40; var ageArray = [20,30,40]; console.log(ageArray); // 创建一个数组,用于存储你喜欢的三个明星的姓名 var nameArray = ['热巴', 'baby', '柳岩']; console.log(nameArray); // 创建一个数据,用于存储50个学生的姓名 var names = ['zs', 'ls', 'ww', 'zl']; console.log(names); //字面量 []; [20,30,40]; ['热巴', 'baby', '柳岩']; ``` ## **获取数组元素** &emsp;&emsp;我们可以根据数组的下标(又叫索引)获取数组中某个元素。数组元素下标从0开始,如果使用一个不存在的下标获取数组元素,将会获取到一个undefined值。 语法格式:格式:数组名\[ 索引 \] &emsp;**索引**又称作**下标** ``` // 功能:获取数组对应下标的那个值,如果下标不存在,则返回undefined。 var nameArray = ['热巴', 'baby', '柳岩']; nameArray[0]; // 热巴 nameArray[2]; // 柳岩 nameArray[3]; // 这个数组的最大下标为2,因此此处返回undefined console.log(nameArray); ``` <br> ## **数组的存储的特点** &emsp;&emsp;我们可以在数组中存储不同类型的元素,但是这样的数组不方便我们处理数据,所以不推荐使用。我们还可以获取数组的长度,获取数组的最后一项,动态改变数组等等。 1. JavaScript数组元素的类型可以不一致(不推荐使用) ``` var arr = ['热巴', 'baby', 18, 19 ]; console.log(arr); ``` 2. 使用length属性获取数组的长度 ``` var names = ['热巴', 'baby', '柳岩']; console.log(names.length); ``` 3. 获取数组的最后一项 ``` var names = ['热巴', 'baby', '柳岩']; console.log(names[names.length-1]); ``` 4. 动态改变(修改或添加元素)数组长度 >[success]格式:数组名[下标/索引] = 值; &emsp;&emsp;如果下标有对应的值,会把原来的值覆盖,如果下标不存在,会给数组新增一个元素。 ``` var names = ['热巴', 'baby', '柳岩']; // 把'热巴'替换成了'幂幂' arr[0] = '幂幂'; // 给数组新增加了一个'圆圆'的值 arr[3] = '圆圆'; //从数组的最后一项的下一个位置开始加入新元素 for (var i = 0; i < 5; i++) { names[names.length] = i+''; } console.log(names); ``` <br> ## **遍历数组** 遍历:遍及所有,历经全部的意思。对数组的每一个元素都访问一次就叫遍历数组。 <br> ### **使用for循环遍历数组** &emsp;&emsp;我们发现,数组索引和for循环次数都是从0开始,所以我们可以把for循环中的循环次数 i 当做数组的索引 index 来使用,这样就可以访问到数组的每一个元素了。 1. 固定格式 ``` for(var i = 0; i < arr.length; i++) { // 数组遍历的固定结构 } ``` 2. 获取数组中的多个元素,遍历(遍布所有,历经全部)数组 ``` //获取数组中的多个元素,遍历(遍布所有,历经全部)数组 var array = []; //动态天10个数组元素 for (var i = 0; i < 10; i++) { array[i] = '我是第' + i + '个元素'; } console.log(array); ``` 3. 正向遍历数组 ``` //1.正向遍历数组,访问数组的每一个元素 for (var i = 0; i < array.length; i++) { console.log(array[i]); } ``` 4. 逆向遍历数组 ``` //2.逆向遍历数组 for (var i = array.length - 1; i >= 0; i--) { console.log(array[i]); } ``` ## **案例** ### 求一组数的和与平均值 需求: &emsp;&emsp;1、定义一个具有5个数值元素的数组,求这个数组中所有元素的和与平均值 &emsp;&emsp;思路:遍历数组将数组元素累加到sum变量中,然后使用sum除以数组的长度求得平均值。 ``` //定义一个数组 var numbers = [2, 3, 5, 2, 8]; var sum = 0; var avg = 0; //遍历数组 for (var i = 0; i < numbers.length; i++) { sum = sum + numbers[i]; } console.log('所有数的和:'+sum); console.log('平均值:'+sum/numbers.length); ``` <br> ### 求一组数中的最大值 需求: &emsp;&emsp;2、求一组数 \[6, 13, 8, 21, 14, 5\] 中的最大值 &emsp;&emsp;需求分析: (1)定义一个变量max,用于存储最大值(为了方便处理,我们可以将max初始化值为数组的第一个元素) (2)用max跟数组的每一个元素比较大小,如果max值小于元素值,则用数组元素值覆盖掉max值,最后得到的max就是整个数组中最大的值。 ``` // 定义一个数组,用于存储一组数值 var arrayNum = [6, 13, 88, 21, 14, 5]; // 定义一个变量,用于存储求出的最大值 var max = arrayNum[0]; // 遍历数组,比较元素的与max的大小 for (var i = 1; i < arrayNum.length; i++) { //比较当前遍历到的元素与max的值的大小,把大的值赋值给max var num = arrayNum[i]; if (max < num) { //将较大的值赋值给max max = num; } } console.log(max);// 88 ``` ### 求一组数中的最大最小值及其所在的位置 需求: &emsp;&emsp;4、求一组数 \[6, 13, 8, 2, 21, 134, 5\] 中的最大最小值及其所在的位置 &emsp;&emsp;需求分析: (1)在求得最大值的同时,将最大值的索引存储起来,遍历结束后即可得到最大值及其下标 (2)同理可求最小下标 ``` //求一组数中的最大值和最小值,以及所在位置 //最大最小值,位置 var numbers = [6, 13, 8, 2, 21, 134, 5]; //假设最大最小值 var max = numbers[0]; var min = numbers[0]; //同时记录最大最小值下标(位置) var maxIndex = 0; var minIndex = 0; for (var i = 1; i <= numbers.length; i++) { if (max < numbers[i]) { max = numbers[i]; maxIndex = i; } if (min > numbers[i]) { min = numbers[i]; minIndex = i; } } console.log('最小值:'+min, minIndex); console.log('最大值:'+max, maxIndex); ``` <br> ### **分隔数组(重要)** 需求: &emsp;&emsp;5、将字符串数组 \['孙悟空', '比克大魔王', '天津饭', '克林', '布尔玛'\] 的元素用 | 分割成一个字符串,比如 &emsp;&emsp;' 孙悟 | 比克大魔王 | 天津饭 | 克林 | 布尔玛 '. &emsp;&emsp;需求分析: (1)遍历数组,在数组每一个元素面后拼接 | 需求注意的问题: 1、代码中的分隔符 | 不能写死 2、最后一个元素后面不能有分隔符 ``` //将字符串数组用|或其他符号分割成一个字符串 var names = ['孙悟空', '比克大魔王', '天津饭', '克林', '布尔玛']; var str = ''; for (var i = 0; i < names.length; i++) { //names[i] = names[i] + separator; str += names[i] + '|'; } console.log(names); console.log(str); ``` ``` //解决两个小问题:(1)分隔符写死的问题;(2)最后一项有多余分隔符的问题 var names = ['孙悟空', '比克大魔王', '天津饭', '克林', '布尔玛']; var separator = '|'; var str = names[0]; for (var i = 1; i < names.length; i++) { //names[i] = names[i] + separator; str += separator + names[i]; } console.log(names); console.log(str); ``` <br> ### **替换数组中指定的元素(重要)** 需求: &emsp;&emsp;6、将数组 \[6, 13, 0, 8, 2, 0, 21, 14, 0, 5\] 中的元素为 0 的项去掉,即将不为0的值存入一个新的数组,将新数组输出到浏览器控制台 &emsp;&emsp;需求分析: (1)遍历数组,获取到所有非0元素 (2)将非0元素存储到新数组中,输出 &emsp;&emsp;注意: &emsp;&emsp;将非0数据存储到新数组的时候,每个元素在存储到新数组时的位置,应该是新数组的最后一个元素的下一个位置。 ``` // 定义一个数组 var array = [6, 13, 0, 8, 2, 0, 21, 14, 0, 5]; // 定义一个新的数组,用于存储不为0的元素 var newArray = []; // 遍历array数组,将数组中不为0的元素存储到newArray中 for (var i = 0; i < array.length; i++) { // 判断当前遍历到的元素是否是为0 if (array[i]!==0) { // 将array数组中的元素存储到newArray中 // newArray[i] = array[i];// 问题:导致newArray中元素的索引不连续 // 将array中非0元素添加到newArray中的最后一个元素的下一个位置中 newArray[newArray.length] = array[i]; } } console.log(array); console.log(newArray); ``` <br> ### **翻转数组(重要)** 需求: &emsp;&emsp;7、将数组 \['孙悟空', '琪琪', '克林', '龟仙人'\] 翻转,得到新数组 \["龟仙人", "克林", "琪琪", "孙悟空"\] &emsp;&emsp;需求分析: (1)逆向遍历数组,将数组的元素存储到新数组中 &emsp;&emsp;注意: &emsp;&emsp;元素存储到新数组时的下标处理(参考上一题 “替换指定的元素”)。 ``` // 翻转数组 var names = ['孙悟空', '琪琪', '克林', '龟仙人']; var reverse = []; for (var i = names.length-1; i >=0; i--) { reverse[reverse.length] = names[i]; } console.log(reverse); ``` ### **冒泡排序(重要)** 需求: &emsp;&emsp;8、将一组数\[9, 6, 7, 1, 5, 2\] 从小到大排序 &emsp;&emsp;需求分析: &emsp;&emsp;(1)如下图第一趟,将数组元素前一个与后一个比较大小,如果前一个大于后一个,则交换这两个元素的位置。这一趟做了5次比较,即 “ 数组长度-1 ”次比较。 &emsp;&emsp;(2)如下图第二趟,将数组元素前一个与后一个比较大小,如果前一个大于后一个,则交换这两个元素的位置。这一趟做了4次比较,即 “ 数组长度-2 ”次比较。 &emsp;&emsp;(3)以此类推,第N趟时,做 “ 数组长度-N ” 次比较。 ![](images/冒泡排序04.png) &emsp;&emsp;注意,在循环过程中,比较次数会随着比较趟数的增加而减少,在代码中, i 和 j 会形成这样的关系: &emsp;&emsp;j < arr.length - i , 如下代码: ``` //冒泡排序,从小到大的排序 var arr = [9, 6, 7, 1, 5, 2]; //外层循环:控制比较的趟数 for (var i = 1; i <= arr.length - 1; i++) { //内层循环:控制每一趟的比较次数,判断元素大小,交换元素位置 for (var j = 1; j <= arr.length - i; j++) { //判断元素大小 if (arr[j-1] > arr[j]) { //交换元素位置 var temp = arr[j-1]; arr[j-1] = arr[j]; arr[j] = temp; } } } console.log(arr); ``` &emsp;&emsp;6个元素的一组数可能只需要比较一趟就已经排好序了。但如果使用上述代码,不管有没有排好序,都会执行arr.length - 1趟,每一趟会执行arr.length - 1 - i此比较,这样的循环不合理!我们可以对以上的冒泡排序代码进行优化。 &emsp;&emsp;优化思路:如果这组数没有排好序,那么就一定会进行数据交换,我们创建一个变量来记录每一趟中是否交换过数据,然后根据这个变量判断这一趟是否已经排好序。 ``` //优化:解决已经排序好但还继续循环比较的问题 var arr = [86, 57, 61, 18, 40, 34]; var conut = 0; //外层循环:控制比较的趟数 for (var i = 0; i < arr.length - 1; i++) { //假设已经排序完成 var isOver = true; //内层循环:控制每一趟的比较次数,判断元素大小,交换元素位置 for (var j = 0; j < arr.length - 1 - i; j++) { //判断元素大小 if (arr[j] > arr[j + 1]) { //还未排序完成 isOver = false; //交换元素位置 var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } if (isOver) { break; } } console.log(arr); console.log(conut); ```