W06|把資料留下來:一維串列的存取與寫入
今天完成後,我可以
- 使用中括號建立一個一維串列,並理解索引從
0開始。 - 根據座號、月份等題意資料,換算出正確的串列索引。
- 使用
資料[索引]讀取內容,也能把新資料寫入指定位置。 - 題目編號從
1開始時,能判斷是否多保留第0格,讓編號與索引對齊。 - 用
for迴圈依序存取串列中的多筆資料,並把程式分成輸入、處理與輸出三個階段。
一、教師示範與課中跟做
1-1|b022 成績公布(40分)
數學用下標表示位置,例如\(L_1\)、\(L_2\)、\(L_3\)⋯⋯;Python用中括號寫索引。
L只是我們替串列取的變數名稱,不是Python規定的寫法。
先猜,再執行:
依序試print(L[2]) → print(L[3]) → print(L[0]) → print(L[5])。哪個取到第一筆?哪一次出錯?
接著回到b022。10位同學的成績依座號是85、35、65、27、68、94、20、100、58、78。前五筆可以這樣放:
選一種配置,再決定輸入座號p後要查詢哪個索引。
看教師示範時,只要追蹤四個問題:
- Python串列的第一格,索引是多少?
- 你選擇把1號同學的成績放在
L[0]還是L[1]? - 輸入座號
p後,L[____]應填什麼,才能和你的配置一致? - 你的串列總共有幾格?
L[10]在你的配置中能不能存取?
依你選擇的配置,完成查詢骨架:
兩種配置的Python索引都從0開始;串列怎麼建立,查詢時就要用相同的對應方式。
同一個中括號,也能指定要修改的位置
完成查詢後,先猜哪個數字會被改掉,再執行觀察:
L[2]寫在print()裡是讀取該位置;寫在等號左邊,則是修改該位置。
看見IndexError時
如果索引超出串列範圍,Python會顯示IndexError。先檢查你的串列建立了幾格,再確認要存取的索引有沒有超出最後一格:不保留第0格時最後索引是9;多保留第0格時最後索引是10。
二、一維串列基本操作速查表
忘記寫法時,先從「現在要建立、讀取、修改、輸入還是輸出」判斷要查哪一列。本週只整理固定長度串列會用到的基本操作。
2-1|建立、存取與修改
以下用i表示要存取的索引(位置)。
| 想做的事 | Python寫法 | 意思 |
|---|---|---|
| 直接建立已知資料 | L = [85, 35, 65] |
依照寫入順序建立3格資料 |
建立n格 |
L = [0] * n |
建立索引0到n - 1的n格 |
| 讀取一格 | score = L[i] |
把指定位置的資料讀入score |
| 修改一格 | L[i] = score |
把score寫入指定位置 |
| 輸出一格 | print(L[i]) |
只輸出指定位置的資料 |
| 暫時查看整個串列 | print(L) |
用來除錯;會出現中括號與逗號,通常不能直接當成題目答案 |
2-2|用同一個程式輸入與輸出n筆資料
按「播放」或「下一步」,觀察依序輸入4、95、67、88、76時,程式如何先將成績寫入串列,再逐格讀取並輸出。動畫中的i代表目前的索引位置,縮排處都使用4格空白。
第一個for把每筆輸入寫入L[i];第二個for讓i從0重新開始,讀出L[i]並逐行輸出。
三、課中獨立練習
3-1|b020 成績公布-2(60分)
b022的10筆成績原本就寫在程式中;這一題改成由輸入提供n筆成績。因為資料之後還要依座號查詢,不能只處理完就丟掉,必須把每筆成績保存下來。
延續b022的兩種配置:你要把1號同學的成績放在索引0,還是保留第0格、放在索引1?先選好,再讓建立格數、迴圈範圍、寫入索引與查詢索引互相配合。
用座號1與n試查詢:各自應讀到哪一格?
提示:檢查你的配置
第一筆與最後一筆分別寫到哪個索引?迴圈是否剛好讀入n筆?查詢時,座號p和索引是否需要換算?
每筆輸入都要寫進串列
每次input()讀到的成績,都要指定給L[...]的一格,才能在後面依座號查詢。
四、解題後整理
讀取與寫入只差在等號中的位置
請把等號讀成「將右邊的值放進左邊」。先確認這一行真正想改變的是一般變數,還是串列中的某一格。
根據題意選擇索引方式
如果資料只需要依序存放與走訪,可以準備n格,使用索引0到n - 1:
如果題目反覆使用1到n的座號、月份或編號,可以多保留第0格:
Python仍然有索引0,只是第二種配置刻意不使用它,換取「題目編號等於串列索引」。
五、課後挑戰
課後題可以查閱講義、互相討論或尋找資料,主要目的是嘗試把本週方法延伸到不同情境;課堂中的b022與b020才是本週主要的現場練習。建議先完成a062與b023,再依時間與狀況挑戰a066和b021。
| 題目 | 配分 | 定位 | 本週目標 |
|---|---|---|---|
a062 這個月有幾天 |
20分 | 主要練習 | 把月份轉成索引,讀取固定串列中的一筆資料 |
b023 算平均-串列版 |
20分 | 主要練習 | 先保存全部成績,再用第二個迴圈計算總和 |
a066 今年的第幾天 |
30分 | 進階挑戰 | 用迴圈讀取前面月份的天數並累加 |
b021 誰是學霸-索引挑戰 |
30分 | 進階挑戰 | 只記錄目前最高分所在的索引 |
5-1|a062 這個月有幾天(20分)
先把平年每個月的天數按照順序放進串列。這題可以在最前面多放一個0,讓month_days[1]直接代表1月、month_days[2]直接代表2月。這次請使用串列查表,不要寫12個月份的if或elif。
提示:月份如何換成索引?
第0格保留不用後,月份可以直接當成索引。請確認這個串列總共應該準備幾格。
共用工具|把程式分成Input、Process、Output
程式不外乎是三個階段:
Input 輸入 → Process 處理 → Output 輸出
還沒使用串列時,資料筆數很多或不固定,通常只能一邊輸入、一邊處理:
學會串列後,可以先把輸入全部留下,再分開處理:
Input:把所有資料存進串列
→ Process:使用串列中的資料計算答案
→ Output:輸出題目要求的結果
b023與b021都先把成績存進串列,再以不同的Process處理。b021可以沿用從索引0存放的方式,也可以保留第0格;走訪範圍與最後輸出的座號要和選擇的配置一致。
5-2|b023 算平均-串列版(20分)
這題在W04已經做過,當時每輸入一筆就直接加入總和。這次即使JMJ已顯示AC,也請重新寫一個串列版本:
注意:這不是單純重做舊題。 後面的題目會要求先算出平均,再回頭逐筆判斷資料;如果資料沒有先存進串列,就無法進行第二輪處理。請務必依照本次要求,使用兩個迴圈完成串列版。
Input:第一個迴圈輸入所有成績並寫入串列
→ Process:第二個迴圈從串列讀取每筆成績並累加,再計算平均
→ Output:輸出平均
本次不使用sum(),重點是練習把資料完整保存後,再次走訪使用。
需要時展開:兩階段骨架
完成後補充:加總的簡寫
下面兩種寫法意思相同,只選一種,不要連續執行兩行。空格代表本次要加的數值。
完整指定寫法:
簡寫:
現階段先用完整指定寫法練習加總。簡寫看得懂即可,不要求使用。
5-3|a066 今年的第幾天(30分)
這題只需要讀取月份天數,不需要修改串列。先將答案設為當月日期,再把「目標月份以前」的每個月天數加進答案。
例如5月8日需要累加1月、2月、3月、4月,再加上8日;不能把5月的全部天數也加進去。
提示一:讀取同一行的月份與日期
以下兩種寫法擇一使用。沿用W03的寫法:
或使用精簡寫法:
精簡寫法中的map(int, ...)會把切開的兩份資料轉成整數,交給month與day。
提示二:決定迴圈終點
如果輸入1月,前面沒有任何月份,迴圈應執行0次;如果輸入5月,迴圈應依序讀取1月到4月的天數。
5-4|b021 誰是學霸-索引挑戰(30分)
這題在W05曾用max_score與座號兩個變數完成。這次先把所有成績存進串列,再改成只記錄「目前最高分所在的索引」。你可以從索引0存第一筆,也可以保留第0格;最後依自己的配置輸出座號。
注意:請不要直接交回W05的舊程式。 後續的搜尋與排序會經常需要記錄「某個值位於哪一格」,再用索引回到串列取得或修改資料。請務必練習只記錄最佳位置,並透過索引讀取對應成績。
處理最高分時,只用一個變數記錄目前冠軍的索引,不另外保存最高分。
提示一:最高分不必另外保存
如果目前冠軍的索引記在best_i,它的成績可以隨時用下列寫法取得:
提示二:用成績比較,記錄最佳索引
初始冠軍要選哪位同學?迴圈要從哪位同學開始比較?找到更高分時,要更新同學的索引,還是分數?
六、完成後自我檢查
- 我知道長度為
n的串列,合法索引是0到n - 1。 - 我能依串列的配置,判斷從
1開始的座號或月份應對到哪個索引。 - 我知道需要題目編號與索引對齊時,可以多保留第
0格。 - 我能分辨
score = L[i]與L[i] = score。 - 我能根據用途選擇
[0] * n或[0] * (n + 1)。 - 我能使用迴圈依序讀取串列中的每筆資料。
- 我能把程式整理成Input、Process與Output三個階段。
- 我遇到
IndexError時,會先檢查索引是否超出範圍。 - 重做
b023時,我先保存全部資料,再使用第二個迴圈累加。 - 重做
b021時,我只記錄最佳索引,用它查出成績,再依串列配置輸出座號。
