APCS 必學map() 函式 : 一行解決批次轉換

作者:Howshin Wang
#Python#APCS#map函式#批次處理#for迴圈#列表處理#型態轉換#程式入門#lambda#高階函式
APCS 必學map() 函式 : 一行解決批次轉換

TL;DR 重點摘要

  • map() 是 Python 的「批次處理工具」,可以一次對整個列表的每個元素套用同一個函式
  • 配合 intfloat 是 APCS 處理測資最常見的組合,寫起來比 for 迴圈短很多
  • 不只能用在型態轉換,還可以做開根號、絕對值、四捨五入等批次運算
  • 學會 map() 後,你的程式碼會變短一半,而且更接近 Python 老手的寫法
  • 這個概念在資料處理、競賽程式、甚至未來學機器學習都會反覆出現

目錄


為什麼要學 map()

上一篇我們學會了 input().split() 把一行字串拆成列表,但拆出來的每個元素都還是字串。要讓電腦把它們當數字運算,就得轉型態。

最直覺的做法是寫一個 for 迴圈一個一個轉,但這樣會讓程式碼變得很冗長。map() 就是來解決這個問題的——一行做完一整個迴圈該做的事。

對 APCS 考生來說,map() 還有另一個好處:寫得越短,出錯的機會越少。考試時間有限,能省的程式碼就盡量省。


從 for 迴圈到 map():同一件事的兩種寫法

假設我們有一串字串 ["10", "20", "30"],想全部轉成整數。

用 for 迴圈寫:

strings = ["10", "20", "30"]
numbers = []
for s in strings:
    numbers.append(int(s))
print(numbers)
# 輸出: [10, 20, 30]

四行程式碼,要建一個空列表、寫迴圈、用 append() 加進去。

用 map() 寫:

strings = ["10", "20", "30"]
numbers = list(map(int, strings))
print(numbers)
# 輸出: [10, 20, 30]

一行解決。map() 做的事情其實就是:「把 int 這個函式套用到 strings 的每一個元素上」。


map() 的三個常見用法

用法一:批次轉成整數

這是 APCS 最常用的組合:

nums = list(map(int, input().split()))

這行程式碼做了三件事:

  1. input() 讀進一整行
  2. .split() 用空格拆開
  3. map(int, ...) 把每個字串轉成整數

執行範例:

輸入: 5 12 8 3 17
nums = [5, 12, 8, 3, 17]

用法二:批次做數學運算

map() 不只能轉型態,還能套用任何函式。例如算每個數字的絕對值:

nums = [-3, 5, -7, 2]
abs_nums = list(map(abs, nums))
print(abs_nums)
# 輸出: [3, 5, 7, 2]

或是把所有數字四捨五入:

prices = [12.4, 18.7, 9.5, 23.2]
rounded = list(map(round, prices))
print(rounded)
# 輸出: [12, 19, 10, 23]

用法三:配合自訂函式

如果內建函式不夠用,可以自己寫一個:

def square(x):
    return x * x

nums = [1, 2, 3, 4, 5]
squared = list(map(square, nums))
print(squared)
# 輸出: [1, 4, 9, 16, 25]

這個寫法在 APCS 處理「對每筆資料做同樣計算」的題目時非常好用。


map() vs 列表推導式:該用哪個?

Python 裡還有另一個寫法叫「列表推導式(list comprehension)」,做的事情很像:

# map 寫法
nums = list(map(int, input().split()))

# 列表推導式寫法
nums = [int(x) for x in input().split()]

兩種都能達到一樣的效果,APCS 考試也都接受。簡單的判斷原則:

  • 只是套用一個函式(像 intfloatabs)→ 用 map() 比較簡潔
  • 需要加條件或做複雜運算(像「只取偶數的平方」)→ 用列表推導式比較直覺

我們會在系列第四篇詳細介紹列表推導式。現在先把 map() 練熟,APCS 大部分輸入處理都用得到。


使用時容易出錯的地方

問題一:忘記加 list()

nums = map(int, input().split())
print(nums)
# 輸出: <map object at 0x000001>

map() 直接印出來不會看到結果,因為它回傳的是一個「map 物件」,要用 list() 包起來才會變成列表。

問題二:函式不要加括號

# 錯誤寫法
nums = list(map(int(), input().split()))

# 正確寫法
nums = list(map(int, input().split()))

寫成 int() 等於是「現在就執行這個函式」,但 map() 要的是「函式本身」,讓它之後再執行。所以只寫 intfloatabs 這些名字,不加括號。

問題三:多個參數時的搭配

map() 也可以同時處理多個列表。例如把兩個列表對應位置相加:

a = [1, 2, 3]
b = [10, 20, 30]
result = list(map(lambda x, y: x + y, a, b))
print(result)
# 輸出: [11, 22, 33]

lambda 是 Python 的「匿名函式」,簡單來說就是「臨時定義一個小函式」。這個用法在進階題目會看到,初學階段先不用急著掌握。


map() 是進入 Python 高效寫法的第一道關卡。學會它之後,你看 APCS 解題範例會覺得「啊,原來這行程式碼是這個意思」,而不是一片問號。

下一篇我們會聊 f-string 格式化輸出——APCS 評分系統對輸出格式很挑剔,多一個空格、少一個換行都可能拿不到分數。學會 f-string 就能精準控制每一個字元。


AI導師 Python 程式教學 - 隨時可以學習

免費試用

Ah Ha Coding AI 程式教學

?常見問題 FAQ

Q.map() 跟 for 迴圈做的事情一樣,那為什麼還要學 map()

兩者結果一樣,但 map() 寫起來短得多,而且更接近「一次處理整批資料」的思考方式。在 APCS 考試裡,程式碼越短代表打字時間越少、出錯機會越低。例如把字串列表轉成整數列表,for 迴圈要 4 行,map() 只要 1 行:

numbers = list(map(int, strings))

Q.為什麼 map(int, ...) 不能寫成 map(int(), ...)

因為 map() 要的是「函式本身」,讓它之後再對每個元素執行;而 int() 加上括號代表「現在就執行這個函式」。

# 錯誤
nums = list(map(int(), input().split()))

# 正確
nums = list(map(int, input().split()))

只要記住:傳給 map() 的函式名字後面不加括號

Q.為什麼 map() 印出來不是列表,而是 <map object at ...>

因為 map() 回傳的是一個「map 物件」(生成器類型),它要等你真的用到資料時才會計算結果。要看到實際內容,需要用 list() 包起來:

nums = list(map(int, input().split()))
print(nums)  # 這樣才會看到 [10, 20, 30]

或是用 for 迴圈走訪也可以。

Q.什麼時候該用 map(),什麼時候該用列表推導式?

簡單的判斷原則:

  • 只是套用一個現成的函式(像 intfloatabsround)→ 用 map() 比較簡潔
  • 需要做運算或加條件(像「取每個數的平方」、「只取偶數」)→ 用列表推導式比較直覺

例如:

# 套用單一函式 → map() 最短
nums = list(map(int, input().split()))

# 需要運算 → 列表推導式更清楚
squares = [x * x for x in nums]

Q.map() 可以同時處理兩個列表嗎?

可以,搭配 lambda(匿名函式)就能對兩個列表的對應位置做運算:

a = [1, 2, 3]
b = [10, 20, 30]
result = list(map(lambda x, y: x + y, a, b))
# 結果: [11, 22, 33]

不過這個寫法比較進階,初學階段先把單一列表的 map() 練熟就好。

Q.map() 只能用內建函式嗎?可以用自己寫的函式嗎?

可以。任何能接受參數並回傳值的函式都能傳給 map()

def square(x):
    return x * x

nums = [1, 2, 3, 4, 5]
squared = list(map(square, nums))
# 結果: [1, 4, 9, 16, 25]

這個用法在 APCS「對每筆資料做同樣計算」的題目裡特別好用。