程式內若需要宣告多個變數,且需要依序存取每個變數,此時適合使用陣列取代多個變數。使用迴圈可以存取陣列每一個元素,會比存取多個變數的程式碼簡潔。以下介紹一維陣列與二維陣列。
3-1. 一維陣列
3-1-1 一維陣列的概念
陣列(Array)是將相同資料型別的多個變數結合在一起,每個陣列中的元素皆可視為變數使用。陣列佔有連續的記憶體空間,提供索引值(Index)存取陣列內個別元素。陣列第一個元素其索引值為0,第二個元素其索引值為1,第三個元素其索引值為2,依此類推,n個元素的陣列,存取陣列最後一個元素其索引值為n-1。每個索引值對應唯一一個陣列元素,因此,我們只要指定陣列名稱與索引值就可以存取陣列中指定的元素。例如:存取成績陣列索引值為0的元素,就可以存取成績陣列的第一個元素。
以下範例說明不使用陣列與使用陣列的差異。若程式中要計算全班30位同學的資訊科成績的總分,不使用陣列則需宣告30個變數(例如:score1、score2、…、score30)儲存30個資訊科成績,使用「sum=score1+score2+…+score30」加總,獲得資訊科全班總分。若使用陣列,則可以使用迴圈控制陣列索引值存取與累加陣列內每一個元素,達成加總的功能。尤其在樣本空間放大時更明顯,如果要計算全年級國文科總分,全年級有500為同學,使用宣告500個變數(例如:score1、score2、…、score500)的方式,就加總而言需寫成「sum=score1+score2+…+ score500」,這樣的程式非常不易閱讀與撰寫,所以才有陣列概念的形成,善用陣列與迴圈可以簡化程式碼。
使用一維陣列取代多個變數,並利用迴圈控制陣列索引值,進而可以存取一維陣列的所有元素。存取到陣列內所有元素就可以進行加總、搜尋與計數等運算。例如:使用一維陣列info儲存全班資訊科期末考成績,再利用迴圈與陣列索引值概念可以存取陣列中所有元素,計算出資訊科成績的全班總分。
利用迴圈變數結合陣列索引值,經由控制陣列索引值可以存取陣列中所有元素。使用一維陣列儲存資訊科成績所撰寫程式碼較簡潔,不需要每一個同學宣告一個變數儲存成績,且新增學生時只需要增加陣列的元素個數與修改迴圈變數的數值範圍。
3-1-2 一維陣列的操作
(ch3\3-1-2一維陣列的操作.py)
(一)宣告與初始化
程式中使用陣列需先宣告,宣告為指定陣列名稱與陣列的元素個數。初始化意指設定陣列每個元素的值,在程式中指定陣列元素的值。使用「A[0]=1」就可以將陣列A的第一個元素設定為1,也是將數值1寫入陣列A的第一個元素,以下就介紹宣告與初始化的語法。
我們來看看上述程式範例陣列A的記憶體狀態,如下圖。
除了可以在宣告陣列程式中初始化,也可以於宣告時同時初始化,如下表。
(二)讀取一維陣列
以下介紹讀取一維陣列,可以使用A[0]讀取陣列A的第一個元素,A[1]讀取陣列A的第二個元素,以此類推。利用迴圈變數與陣列索引值結合,經由控制陣列索引值可以存取陣列中所有元素,陣列元素A[i]的i值就是陣列索引值。當i等於0,就指向陣列A的第一個元素,其值為1;當i等於1,就指向陣列A的第二個元素,其值為2,依此類推。下表為迴圈變數與陣列索引值結合範例。
以上為印出陣列所有元素的演算法,每一個元素都需要讀取與顯示在螢幕上,演算法效率為O(n),n為陣列的元素個數。
(三)插入元素到一維陣列
假設陣列C有5個元素,分別是「1, 2, 3, 4, 5」,如下圖。
當要插入元素6到陣列C的第3個元素,則陣列C需要增加一個元素,變成6個元素,如下圖,使用「C.append(0)」,新增數值0到陣列C的最後。
接著使用迴圈for與「C[i] = C[i-1]」每個元素向右移一格,迴圈變數i由5到3,每次遞減1,如下圖。
接著使用「C[2] = 6」設定陣列C第3個元素為6,如下圖。
到此完成插入一個元素到陣列C的第3個元素,此為陣列的插入演算法,演算法最花時間在是每個陣列元素右移一格平均需要花O(n),n為陣列的元素個數。陣列插入元素的完整程式如下。
(四)從一維陣列刪除元素
假設陣列C有5個元素,分別是「1, 2, 3, 4, 5」,如下圖。
當要刪除陣列C的第2個元素,則將第3個元素移動到第2個元素,第4個元素移動到第3個元素,使用迴圈for與「C[i] = C[i+1]」每個元素向左移一格,迴圈變數i由1到3,每次遞增1,如下圖。
接著使用「C.pop(-1)」刪除陣列C最後一個元素,如下圖。
到此完成從陣列C刪除第2個元素,此為陣列刪除演算法,演算法最花時間在是每個陣列元素左移一格平均需要花O(n),n為陣列的元素個數。陣列刪除元素的完整程式如下。
(五)複製一維陣列
假設陣列C有5個元素,分別是「1, 2, 3, 4, 5」,如下圖。
當要複製陣列C的每一個元素到陣列D,使用迴圈for與「D[i] = C[i]」,迴圈變數i由0到4,每次遞增1,取出陣列C的每一個元素複製到陣列D。
到此完成從陣列C複製每一個元素到陣列D,此為陣列複製演算法,演算法最花時間是在陣列內每一個元素複製到另一個陣列平均需要花O(n),n為陣列的元素個數。陣列複製元素的完整程式如下。
3-2. 一維陣列的程式實作
3-2-1. 計算成績陣列的總分
(ch3\3-2-1計算成績陣列的總分.py)
題目:取出成績陣列的每一個元素進行加總,計算出成績陣列的總分。
想一想:如何取出成績陣列的每一個元素?
解題想法:將成績資料置於陣列中,再利用迴圈存取陣列中每一個元素進行加總,當每個元素都存取到時就可以得到成績的加總。
(a)程式結果預覽
執行結果顯示在螢幕上,如下圖。
(b)程式碼與解說
第1行:變數sum初始化為0。
第2行:宣告score為整數陣列,且初始化score陣列的第1個元素為90、第2個元素為90、第3個元素為90、第4個元素為80、第5個元素為80、第6個元素為80。
第3到6行:使用for迴圈計算成績陣列score加總值。計算過程中使用變數sum暫存成績加總結果(第4行)。印出陣列score的每個值到螢幕上,設定sep為空字串,表示輸出的字串與變數之間不會有空白鍵(第5行)。印出每加一個成績後,變數sum的值到螢幕上(第6行)。
score[i]的i值可由迴圈控制。當i=0,score[i]相當於為score[0],指向score陣列的第一個元素;當i=1,score[i]相當於score[1],指向score陣列的第二個元素,依此類推。
3-3. 二維陣列
3-3-1. 二維陣列的概念
使用一維陣列儲存全班第一次期中考國文科成績,再利用迴圈與陣列索引概念可以存取陣列中所有元素,計算出國文科成績的總分與平均。有時一維陣列不夠用,例如:計算全班國文、英文、數學、社會與自然等五科成績的總分與平均。可以將國文、英文、數學、社會與自然五科使用五個一維陣列儲存,也可以使用二維陣列儲存,二維陣列每個元素可以使用列與行表示,如下圖,座號3號學生的英文成績為73分,儲存在第2列第3行。使用五個一維陣列需宣告五個不同陣列名稱,每個陣列分開計算加總而獲得各科總分。使用二維陣列可以使用五列,每一列元素代表一個科目的成績,利用巢狀迴圈存取二維陣列的每一個元素,計算每一科的總分。使用二維陣列儲存各科成績所撰寫程式碼較簡潔,且新增科目時只需要增加陣列列數與修改迴圈變數範圍。若計算3個年級五科成績需要15個科目時,使用二維陣列的好處就更為明顯,不需要宣告15個一維陣列,只要宣告一個15列的二維陣列即可。
3-3-2. 二維陣列的操作
所謂二維陣列的宣告是用於定義二維陣列的名稱與陣列中元素的個數,而初始化是指定陣列中元素的值。例如:score = [[0]*40 for i in range(5)],就是宣告一個整數的二維陣列,名稱為score,其列索引值由0到4,共5列,其行索引值0到39,共40行。將其使用表格呈現,如下表。程式中使用score[1][2]可以存取陣列score的第2列第3行元素。
陣列初始化的方法
存取二維陣列
程式中使用陣列的優點為可以使用陣列索引值存取陣列元素。例如:score[1][2]的括號內1與2分別表示為列索引值為1,行索引值為2,表示為陣列score的第2列第3行元素。將索引值改成變數i與變數j,當i等於1且j等於2,則score[i][j]相當於score[1][2],score[i][j]也是表示陣列score的第2列第3行元素。使用迴圈控制變數i與變數j,當變數i與變數j變化時,score[i][j]所對應的元素也會跟著改變。使用索引值存取陣列的概念可以存取陣列中所有元素。
以下為迴圈與陣列索引值存取陣列中元素的範例。
第1行:匯入random函式庫。
第2行:宣告二維陣列名稱為score有5列40行。
第3到5行:使用巢狀迴圈,迴圈變數i控制列,變數j控制行。程式「random.randint(40,100)」隨機產生介於40到100的數值。當i=0,j=0,score[i][j]指向二維陣列score的第1列第1行並將隨機產生的數值儲存入score[0][0];當i=0,j=1,score[i][j]指向二維陣列score的第1列第2行並將隨機產生的數值儲存入score[0][1];當i=0,j=2,score[i][j]指向二維陣列score的第1列第3行並將隨機產生的數值儲存入score[0][2],依此方式,依序產生40個隨機值,填入陣列中第一列。接著產生40個隨機值填入第二列,直到填滿五列。
3-4. 二維陣列的程式實作
3-4-1. 計算各科總分
(ch3\3-4-1計算各科總分.py)
題目:隨機產生二維(5x40)成績陣列(score)每一個陣列元素的數值。假設一列表示一個科目的成績,則此成績陣列可以儲存5科成績。使用程式計算出各科的總分。
想一想:如何使用巢狀迴圈存取二維陣列?
以下為上述問題的參考想法如下。
解題想法:使用巢狀迴圈存取二維陣列的每一個元素。外層迴圈控制列,假設變數i為外層迴圈變數,內層迴圈控制行,假設變數j為內層迴圈變數。初始化變數total為0,用於暫存每一個陣列元素的累加值。當i值等於0,j值變化由0到39,可以存取第一列每一個元素,利用「total = total + score[i][j]」計算總分,最後變數total即為第1科成績的總分。外層迴圈變數i加1,則i值等於1,初始化變數total為0,j值變化一樣由0到39,可以存取第二列每一個元素,利用「total = total + score[i][j]」計算總分,最後變數total即為第2科成績的總分。以此方式即可獲得各科總分。
(a)程式結果預覽
執行結果顯示在螢幕上,如下圖。
(b)程式碼與解說
第1行:匯入random函式庫。
第2行:宣告二維陣列名稱為score有5列40行。
第3到5行:使用巢狀迴圈,迴圈變數i控制列,變數j控制行,程式「random.randint(0,100)」隨機產生介於0到100的數值,儲存入二維陣列score[i][j]。
第6到11行:使用巢狀迴圈計算各科總分。
第7行:先設定總分變數total為0。
第8到10行:內層變數j變化由0到39,存取同一列所有元素值,並使用變數total累計總分(第9行)。顯示每個隨機分數到螢幕上,分數之後串接逗號「,」,設定間隔符號sep為空字串與換行符號end為空字串(第10行)。
第11行:外層迴圈內的最後一行顯示總分。
3-4-2. 矩陣相加
(ch3\3-4-2矩陣相加.py)
題目:設計一個程式計算矩陣相加的結果。矩陣相加概念舉例如下:假設有兩個2x3矩陣A與B相加得另一個2x3矩陣C,矩陣C的第1列第1行元素等於矩陣A第1列第1行元素的值加上矩陣B第1列第1行元素的值;矩陣C的第1列第2行元素等於矩陣A第1列第2行元素的值加上矩陣B第1列第2行元素的值,依此類推,完成矩陣A與B相加獲得矩陣C。
想一想:如何使用巢狀迴圈存取二維陣列?如果要將「陣列A第i列第j行的元素加上陣列B第i列第j行的元素儲存到陣列C第i列第j行的元素」,請問此程式碼該如何撰寫?
以下為上述問題的參考想法如下。
解題想法: 使用巢狀迴圈存取兩個二維2x3陣列A與陣列B的每一個元素,外層迴圈控制列,假設外層迴圈的迴圈變數為i,內層迴圈控制行,假設內層迴圈的迴圈變數為j。當i值等於0,j值由0到2,可以存取陣列A與陣列B第一列每一個元素,利用公式「C[i][j] = A[i][j]+ B[i][j]」,求出陣列C為陣列A與陣列B相加。外層迴圈變數i參考到數列的下一個元素,造成i值增加1,則i值等於1,j值一樣由0到2,可以存取第二列每一個元素,利用公式「C[i][j] = A[i][j]+ B[i][j]」,求出陣列C為陣列A與陣列B相加,陣列C即為陣列A與陣列B矩陣相加的結果。
(a)程式結果預覽
執行結果顯示在螢幕上,如下圖。
(b)程式碼與解說
第1行:產生2列3行的二維陣列,變數A參考到此二維陣列。
第2行:產生2列3行的二維陣列,變數B參考到此二維陣列。
第3行:產生2列3行的二維陣列,且每一個元素為0,變數C參考到此二維陣列。
第4到8行:使用巢狀迴圈計算矩陣相加。
第6行:矩陣C為矩陣A與矩陣B相加。
第7行:顯示矩陣C的每個元素值,串接一個空白字元,設定換行符號end為空字串。
第8行:顯示換行符號。