[TOC]
# 數組
## **概念**
  將多個元素(通常是同一類型)按一定順序排列放到一個集合中,那么這個集合就叫稱之為做數組。
<br>
## **創建數組**
  創建數組也叫**定義數組**,定義一個數組變量跟定義一個基本類型的變量格式幾乎一樣。
  定義數組語法格式:
>[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', '柳巖'];
```
## **獲取數組元素**
  我們可以根據數組的下標(又叫索引)獲取數組中某個元素。數組元素下標從0開始,如果使用一個不存在的下標獲取數組元素,將會獲取到一個undefined值。
語法格式:格式:數組名\[ 索引 \]  **索引**又稱作**下標**
```
// 功能:獲取數組對應下標的那個值,如果下標不存在,則返回undefined。
var nameArray = ['熱巴', 'baby', '柳巖'];
nameArray[0]; // 熱巴
nameArray[2]; // 柳巖
nameArray[3]; // 這個數組的最大下標為2,因此此處返回undefined
console.log(nameArray);
```
<br>
## **數組的存儲的特點**
  我們可以在數組中存儲不同類型的元素,但是這樣的數組不方便我們處理數據,所以不推薦使用。我們還可以獲取數組的長度,獲取數組的最后一項,動態改變數組等等。
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]格式:數組名[下標/索引] = 值;
  如果下標有對應的值,會把原來的值覆蓋,如果下標不存在,會給數組新增一個元素。
```
var names = ['熱巴', 'baby', '柳巖'];
// 把'熱巴'替換成了'冪冪'
arr[0] = '冪冪';
// 給數組新增加了一個'圓圓'的值
arr[3] = '圓圓';
//從數組的最后一項的下一個位置開始加入新元素
for (var i = 0; i < 5; i++) {
names[names.length] = i+'';
}
console.log(names);
```
<br>
## **遍歷數組**
遍歷:遍及所有,歷經全部的意思。對數組的每一個元素都訪問一次就叫遍歷數組。
<br>
### **使用for循環遍歷數組**
  我們發現,數組索引和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]);
}
```
## **案例**
### 求一組數的和與平均值
需求:
  1、定義一個具有5個數值元素的數組,求這個數組中所有元素的和與平均值
  思路:遍歷數組將數組元素累加到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>
### 求一組數中的最大值
需求:
  2、求一組數 \[6, 13, 8, 21, 14, 5\] 中的最大值
  需求分析:
(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
```
### 求一組數中的最大最小值及其所在的位置
需求:
  4、求一組數 \[6, 13, 8, 2, 21, 134, 5\] 中的最大最小值及其所在的位置
  需求分析:
(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>
### **分隔數組(重要)**
需求:
  5、將字符串數組 \['孫悟空', '比克大魔王', '天津飯', '克林', '布爾瑪'\] 的元素用 | 分割成一個字符串,比如
  ' 孫悟 | 比克大魔王 | 天津飯 | 克林 | 布爾瑪 '.
  需求分析:
(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>
### **替換數組中指定的元素(重要)**
需求:
  6、將數組 \[6, 13, 0, 8, 2, 0, 21, 14, 0, 5\] 中的元素為 0 的項去掉,即將不為0的值存入一個新的數組,將新數組輸出到瀏覽器控制臺
  需求分析:
(1)遍歷數組,獲取到所有非0元素
(2)將非0元素存儲到新數組中,輸出
  注意:
  將非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>
### **翻轉數組(重要)**
需求:
  7、將數組 \['孫悟空', '琪琪', '克林', '龜仙人'\] 翻轉,得到新數組 \["龜仙人", "克林", "琪琪", "孫悟空"\]
  需求分析:
(1)逆向遍歷數組,將數組的元素存儲到新數組中
  注意:
  元素存儲到新數組時的下標處理(參考上一題 “替換指定的元素”)。
```
// 翻轉數組
var names = ['孫悟空', '琪琪', '克林', '龜仙人'];
var reverse = [];
for (var i = names.length-1; i >=0; i--) {
reverse[reverse.length] = names[i];
}
console.log(reverse);
```
### **冒泡排序(重要)**
需求:
  8、將一組數\[9, 6, 7, 1, 5, 2\] 從小到大排序
  需求分析:
  (1)如下圖第一趟,將數組元素前一個與后一個比較大小,如果前一個大于后一個,則交換這兩個元素的位置。這一趟做了5次比較,即 “ 數組長度-1 ”次比較。
  (2)如下圖第二趟,將數組元素前一個與后一個比較大小,如果前一個大于后一個,則交換這兩個元素的位置。這一趟做了4次比較,即 “ 數組長度-2 ”次比較。
  (3)以此類推,第N趟時,做 “ 數組長度-N ” 次比較。

  注意,在循環過程中,比較次數會隨著比較趟數的增加而減少,在代碼中, i 和 j 會形成這樣的關系:
  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);
```
  6個元素的一組數可能只需要比較一趟就已經排好序了。但如果使用上述代碼,不管有沒有排好序,都會執行arr.length - 1趟,每一趟會執行arr.length - 1 - i此比較,這樣的循環不合理!我們可以對以上的冒泡排序代碼進行優化。
  優化思路:如果這組數沒有排好序,那么就一定會進行數據交換,我們創建一個變量來記錄每一趟中是否交換過數據,然后根據這個變量判斷這一趟是否已經排好序。
```
//優化:解決已經排序好但還繼續循環比較的問題
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);
```