[TOC]
# 數(shù)組
## **概念**
  將多個(gè)元素(通常是同一類型)按一定順序排列放到一個(gè)集合中,那么這個(gè)集合就叫稱之為做數(shù)組。
<br>
## **創(chuàng)建數(shù)組**
  創(chuàng)建數(shù)組也叫**定義數(shù)組**,定義一個(gè)數(shù)組變量跟定義一個(gè)基本類型的變量格式幾乎一樣。
  定義數(shù)組語(yǔ)法格式:
>[success]var 數(shù)組變量名 = 數(shù)組變量值;
var 數(shù)組變量名 = [元素1,元素2,元素3……];
元素與元素之間用英文逗號(hào)“ , ”隔開(kāi)。
```
//變量
// 創(chuàng)建一個(gè)空數(shù)組
var arr = [];
// 創(chuàng)建一個(gè)數(shù)組,用于存儲(chǔ)3個(gè)年齡,年齡分別為 20,30,40;
var ageArray = [20,30,40];
console.log(ageArray);
// 創(chuàng)建一個(gè)數(shù)組,用于存儲(chǔ)你喜歡的三個(gè)明星的姓名
var nameArray = ['熱巴', 'baby', '柳巖'];
console.log(nameArray);
// 創(chuàng)建一個(gè)數(shù)據(jù),用于存儲(chǔ)50個(gè)學(xué)生的姓名
var names = ['zs', 'ls', 'ww', 'zl'];
console.log(names);
//字面量
[];
[20,30,40];
['熱巴', 'baby', '柳巖'];
```
## **獲取數(shù)組元素**
  我們可以根據(jù)數(shù)組的下標(biāo)(又叫索引)獲取數(shù)組中某個(gè)元素。數(shù)組元素下標(biāo)從0開(kāi)始,如果使用一個(gè)不存在的下標(biāo)獲取數(shù)組元素,將會(huì)獲取到一個(gè)undefined值。
語(yǔ)法格式:格式:數(shù)組名\[ 索引 \]  **索引**又稱作**下標(biāo)**
```
// 功能:獲取數(shù)組對(duì)應(yīng)下標(biāo)的那個(gè)值,如果下標(biāo)不存在,則返回undefined。
var nameArray = ['熱巴', 'baby', '柳巖'];
nameArray[0]; // 熱巴
nameArray[2]; // 柳巖
nameArray[3]; // 這個(gè)數(shù)組的最大下標(biāo)為2,因此此處返回undefined
console.log(nameArray);
```
<br>
## **數(shù)組的存儲(chǔ)的特點(diǎn)**
  我們可以在數(shù)組中存儲(chǔ)不同類型的元素,但是這樣的數(shù)組不方便我們處理數(shù)據(jù),所以不推薦使用。我們還可以獲取數(shù)組的長(zhǎng)度,獲取數(shù)組的最后一項(xiàng),動(dòng)態(tài)改變數(shù)組等等。
1. JavaScript數(shù)組元素的類型可以不一致(不推薦使用)
```
var arr = ['熱巴', 'baby', 18, 19 ];
console.log(arr);
```
2. 使用length屬性獲取數(shù)組的長(zhǎng)度
```
var names = ['熱巴', 'baby', '柳巖'];
console.log(names.length);
```
3. 獲取數(shù)組的最后一項(xiàng)
```
var names = ['熱巴', 'baby', '柳巖'];
console.log(names[names.length-1]);
```
4. 動(dòng)態(tài)改變(修改或添加元素)數(shù)組長(zhǎng)度
>[success]格式:數(shù)組名[下標(biāo)/索引] = 值;
  如果下標(biāo)有對(duì)應(yīng)的值,會(huì)把原來(lái)的值覆蓋,如果下標(biāo)不存在,會(huì)給數(shù)組新增一個(gè)元素。
```
var names = ['熱巴', 'baby', '柳巖'];
// 把'熱巴'替換成了'冪冪'
arr[0] = '冪冪';
// 給數(shù)組新增加了一個(gè)'圓圓'的值
arr[3] = '圓圓';
//從數(shù)組的最后一項(xiàng)的下一個(gè)位置開(kāi)始加入新元素
for (var i = 0; i < 5; i++) {
names[names.length] = i+'';
}
console.log(names);
```
<br>
## **遍歷數(shù)組**
遍歷:遍及所有,歷經(jīng)全部的意思。對(duì)數(shù)組的每一個(gè)元素都訪問(wèn)一次就叫遍歷數(shù)組。
<br>
### **使用for循環(huán)遍歷數(shù)組**
  我們發(fā)現(xiàn),數(shù)組索引和for循環(huán)次數(shù)都是從0開(kāi)始,所以我們可以把for循環(huán)中的循環(huán)次數(shù) i 當(dāng)做數(shù)組的索引 index 來(lái)使用,這樣就可以訪問(wèn)到數(shù)組的每一個(gè)元素了。
1. 固定格式
```
for(var i = 0; i < arr.length; i++) {
// 數(shù)組遍歷的固定結(jié)構(gòu)
}
```
2. 獲取數(shù)組中的多個(gè)元素,遍歷(遍布所有,歷經(jīng)全部)數(shù)組
```
//獲取數(shù)組中的多個(gè)元素,遍歷(遍布所有,歷經(jīng)全部)數(shù)組
var array = [];
//動(dòng)態(tài)天10個(gè)數(shù)組元素
for (var i = 0; i < 10; i++) {
array[i] = '我是第' + i + '個(gè)元素';
}
console.log(array);
```
3. 正向遍歷數(shù)組
```
//1.正向遍歷數(shù)組,訪問(wèn)數(shù)組的每一個(gè)元素
for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}
```
4. 逆向遍歷數(shù)組
```
//2.逆向遍歷數(shù)組
for (var i = array.length - 1; i >= 0; i--) {
console.log(array[i]);
}
```
## **案例**
### 求一組數(shù)的和與平均值
需求:
  1、定義一個(gè)具有5個(gè)數(shù)值元素的數(shù)組,求這個(gè)數(shù)組中所有元素的和與平均值
  思路:遍歷數(shù)組將數(shù)組元素累加到sum變量中,然后使用sum除以數(shù)組的長(zhǎng)度求得平均值。
```
//定義一個(gè)數(shù)組
var numbers = [2, 3, 5, 2, 8];
var sum = 0;
var avg = 0;
//遍歷數(shù)組
for (var i = 0; i < numbers.length; i++) {
sum = sum + numbers[i];
}
console.log('所有數(shù)的和:'+sum);
console.log('平均值:'+sum/numbers.length);
```
<br>
### 求一組數(shù)中的最大值
需求:
  2、求一組數(shù) \[6, 13, 8, 21, 14, 5\] 中的最大值
  需求分析:
(1)定義一個(gè)變量max,用于存儲(chǔ)最大值(為了方便處理,我們可以將max初始化值為數(shù)組的第一個(gè)元素)
(2)用max跟數(shù)組的每一個(gè)元素比較大小,如果max值小于元素值,則用數(shù)組元素值覆蓋掉max值,最后得到的max就是整個(gè)數(shù)組中最大的值。
```
// 定義一個(gè)數(shù)組,用于存儲(chǔ)一組數(shù)值
var arrayNum = [6, 13, 88, 21, 14, 5];
// 定義一個(gè)變量,用于存儲(chǔ)求出的最大值
var max = arrayNum[0];
// 遍歷數(shù)組,比較元素的與max的大小
for (var i = 1; i < arrayNum.length; i++) {
//比較當(dāng)前遍歷到的元素與max的值的大小,把大的值賦值給max
var num = arrayNum[i];
if (max < num) {
//將較大的值賦值給max
max = num;
}
}
console.log(max);// 88
```
### 求一組數(shù)中的最大最小值及其所在的位置
需求:
  4、求一組數(shù) \[6, 13, 8, 2, 21, 134, 5\] 中的最大最小值及其所在的位置
  需求分析:
(1)在求得最大值的同時(shí),將最大值的索引存儲(chǔ)起來(lái),遍歷結(jié)束后即可得到最大值及其下標(biāo)
(2)同理可求最小下標(biāo)
```
//求一組數(shù)中的最大值和最小值,以及所在位置
//最大最小值,位置
var numbers = [6, 13, 8, 2, 21, 134, 5];
//假設(shè)最大最小值
var max = numbers[0];
var min = numbers[0];
//同時(shí)記錄最大最小值下標(biāo)(位置)
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>
### **分隔數(shù)組(重要)**
需求:
  5、將字符串?dāng)?shù)組 \['孫悟空', '比克大魔王', '天津飯', '克林', '布爾瑪'\] 的元素用 | 分割成一個(gè)字符串,比如
  ' 孫悟 | 比克大魔王 | 天津飯 | 克林 | 布爾瑪 '.
  需求分析:
(1)遍歷數(shù)組,在數(shù)組每一個(gè)元素面后拼接 |
需求注意的問(wèn)題:
1、代碼中的分隔符 | 不能寫死
2、最后一個(gè)元素后面不能有分隔符
```
//將字符串?dāng)?shù)組用|或其他符號(hào)分割成一個(gè)字符串
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);
```
```
//解決兩個(gè)小問(wèn)題:(1)分隔符寫死的問(wèn)題;(2)最后一項(xiàng)有多余分隔符的問(wèn)題
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>
### **替換數(shù)組中指定的元素(重要)**
需求:
  6、將數(shù)組 \[6, 13, 0, 8, 2, 0, 21, 14, 0, 5\] 中的元素為 0 的項(xiàng)去掉,即將不為0的值存入一個(gè)新的數(shù)組,將新數(shù)組輸出到瀏覽器控制臺(tái)
  需求分析:
(1)遍歷數(shù)組,獲取到所有非0元素
(2)將非0元素存儲(chǔ)到新數(shù)組中,輸出
  注意:
  將非0數(shù)據(jù)存儲(chǔ)到新數(shù)組的時(shí)候,每個(gè)元素在存儲(chǔ)到新數(shù)組時(shí)的位置,應(yīng)該是新數(shù)組的最后一個(gè)元素的下一個(gè)位置。
```
// 定義一個(gè)數(shù)組
var array = [6, 13, 0, 8, 2, 0, 21, 14, 0, 5];
// 定義一個(gè)新的數(shù)組,用于存儲(chǔ)不為0的元素
var newArray = [];
// 遍歷array數(shù)組,將數(shù)組中不為0的元素存儲(chǔ)到newArray中
for (var i = 0; i < array.length; i++) {
// 判斷當(dāng)前遍歷到的元素是否是為0
if (array[i]!==0) {
// 將array數(shù)組中的元素存儲(chǔ)到newArray中
// newArray[i] = array[i];// 問(wèn)題:導(dǎo)致newArray中元素的索引不連續(xù)
// 將array中非0元素添加到newArray中的最后一個(gè)元素的下一個(gè)位置中
newArray[newArray.length] = array[i];
}
}
console.log(array);
console.log(newArray);
```
<br>
### **翻轉(zhuǎn)數(shù)組(重要)**
需求:
  7、將數(shù)組 \['孫悟空', '琪琪', '克林', '龜仙人'\] 翻轉(zhuǎn),得到新數(shù)組 \["龜仙人", "克林", "琪琪", "孫悟空"\]
  需求分析:
(1)逆向遍歷數(shù)組,將數(shù)組的元素存儲(chǔ)到新數(shù)組中
  注意:
  元素存儲(chǔ)到新數(shù)組時(shí)的下標(biāo)處理(參考上一題 “替換指定的元素”)。
```
// 翻轉(zhuǎn)數(shù)組
var names = ['孫悟空', '琪琪', '克林', '龜仙人'];
var reverse = [];
for (var i = names.length-1; i >=0; i--) {
reverse[reverse.length] = names[i];
}
console.log(reverse);
```
### **冒泡排序(重要)**
需求:
  8、將一組數(shù)\[9, 6, 7, 1, 5, 2\] 從小到大排序
  需求分析:
  (1)如下圖第一趟,將數(shù)組元素前一個(gè)與后一個(gè)比較大小,如果前一個(gè)大于后一個(gè),則交換這兩個(gè)元素的位置。這一趟做了5次比較,即 “ 數(shù)組長(zhǎng)度-1 ”次比較。
  (2)如下圖第二趟,將數(shù)組元素前一個(gè)與后一個(gè)比較大小,如果前一個(gè)大于后一個(gè),則交換這兩個(gè)元素的位置。這一趟做了4次比較,即 “ 數(shù)組長(zhǎng)度-2 ”次比較。
  (3)以此類推,第N趟時(shí),做 “ 數(shù)組長(zhǎng)度-N ” 次比較。

  注意,在循環(huán)過(guò)程中,比較次數(shù)會(huì)隨著比較趟數(shù)的增加而減少,在代碼中, i 和 j 會(huì)形成這樣的關(guān)系:
  j < arr.length - i , 如下代碼:
```
//冒泡排序,從小到大的排序
var arr = [9, 6, 7, 1, 5, 2];
//外層循環(huán):控制比較的趟數(shù)
for (var i = 1; i <= arr.length - 1; i++) {
//內(nèi)層循環(huán):控制每一趟的比較次數(shù),判斷元素大小,交換元素位置
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);
```
  6個(gè)元素的一組數(shù)可能只需要比較一趟就已經(jīng)排好序了。但如果使用上述代碼,不管有沒(méi)有排好序,都會(huì)執(zhí)行arr.length - 1趟,每一趟會(huì)執(zhí)行arr.length - 1 - i此比較,這樣的循環(huán)不合理!我們可以對(duì)以上的冒泡排序代碼進(jìn)行優(yōu)化。
  優(yōu)化思路:如果這組數(shù)沒(méi)有排好序,那么就一定會(huì)進(jìn)行數(shù)據(jù)交換,我們創(chuàng)建一個(gè)變量來(lái)記錄每一趟中是否交換過(guò)數(shù)據(jù),然后根據(jù)這個(gè)變量判斷這一趟是否已經(jīng)排好序。
```
//優(yōu)化:解決已經(jīng)排序好但還繼續(xù)循環(huán)比較的問(wèn)題
var arr = [86, 57, 61, 18, 40, 34];
var conut = 0;
//外層循環(huán):控制比較的趟數(shù)
for (var i = 0; i < arr.length - 1; i++) {
//假設(shè)已經(jīng)排序完成
var isOver = true;
//內(nèi)層循環(huán):控制每一趟的比較次數(shù),判斷元素大小,交換元素位置
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);
```
