iT邦幫忙

4

【Python 超入門】(8) break/continue 邏輯- 造謠者向其它求職者說:「我已經拿到這份工作了,你們可以回家了」

大家好,我是「心原一馬」,內心原來一心喜歡打程式碼。
上一篇中,我們教大家如何使用for/while迴圈,
for迴圈可以遍歷列表,
而while迴圈可以在條件不滿足前一直執行,
但有時候,我們也會有需要提早跳出迴圈的情境,
我們可以用下面這個故事來理解…

我的專長是造謠

有一個人去應徵一份工作,
在履歷上寫著「專長: 造謠。」
面試官看了覺得很新奇,跟那人說:「那你造一次謠給我們看看。」
只見那個人走出面試會議室,
跟其它排隊等候面試的求職者說:「我已經錄取這份工作了,你們可以回家了。」

好的,那這段故事在比喻什麼呢?
其實啊,會需要提早跳出迴圈的情況就像公司徵才過程一樣,
假設公司職缺只開一個,
一開始主管會需要面試所有應徵者,
但一旦主管確信他已經找到非常適合的人選,
那麼後面的人可能就不必再通知面試了,
這時徵才可能就會提早結束。

break指令- 提早結束迴圈

在多數程式語言中,提早結束迴圈的指令是break
我們試著寫出這段邏輯看看:
(請注意,以下只是表達一段程式邏輯,並不是真正可執行的程式碼哦~)

for 求職者 in 求職者名單:
    面試求職者
    if 找到適合的人選:
        break

又或者,你是非常優秀的人才,
你報名參加多間心目中好公司的面試,
那麼你可能決定如果有公司錄取自己了,
後面幾家公司的面試就不去了。
(這邊不考慮等候錄取通知和面試時間可能重疊的情境,假設都是一家公司面完才去下一家)
那麼可以用以下的邏輯表達:

for 公司 in 心目中好公司名單:
    參加公司面試
    if 被公司錄取:
        break

對了,發現了嗎?
break通常會跟if搭配使用,
因為我們通常是滿足某個條件才會提早跳出迴圈,
如果你寫:

for 公司 in 心目中好公司名單:
    參加公司面試
    break

這段邏輯沒有跟if搭配,
表示不論如何你只會參加第一間公司面試,
後面公司都不去了。
所以我們幾乎不會單獨使用break指令。

來看看幾個可以執行的程式碼例子吧:

範例1: 我要錄取第一個英文名字開頭為'D'的人

(此範例只是為了方便舉例,請勿當真)
假設我們用candidates 變數表示等候應徵的求職者,
而主管想要錄取英文名字開頭為'D'的人選,一旦找到人選面試流程就結束。
程式如下:

candidates = ['Alice', 'Bob', 'Cindy', 'Daisy', 'Eve', 'Fairy', 'David'] 
for candidate in candidates:
    print('輪到 ' +candidate+ ' 面試')
    if candidate[0]=='D': #如果字串的第一個字為'D'
        print('恭喜 ' +candidate+ ' 錄取')
        break

結果:
輪到 Alice 面試
輪到 Bob 面試
輪到 Cindy 面試
輪到 Daisy 面試
恭喜 Daisy 錄取

continue指令- 你被跳過了

程式語言中,還有一個跟break相似的指令,continue
那這兩個指令有什麼差別呢?
我們繼續用面試的例子來說明。
如果for像面試官一樣,
對名單上的所有人進行面試,
那麼,

  • break指令是直接跳出整個面試流程,相當於後面的人都不必面試了
  • continue指令則是跳過該應徵者,繼續進行後面的面試

寫成邏輯就像這樣:

for 求職者 in 求職者名單:
    面試求職者
    if 求職者條件不足:
        continue
    (註: 如果求職者沒有被continue指令跳過) 該求職者被納入考慮名單中

再跟break邏輯比較一下:

for 求職者 in 求職者名單:
    面試求職者
    if 找到適合的人選:
        break

雖然breakcontinue都有跳過的意思,
break是直接跳出整個迴圈,
continue只是跳過當次迴圈中接下來的指令,迴圈繼續執行。

範例2: 合適的人選進入第二關

範例1中,只憑應徵者的名字來決定是否錄取,
給人有偏見的感覺,
因此,主管決定改用一個較公正的方法來徵才:
先讓他們參加第一階段的考試,80分以上者可以進入第二關。
這次我們用candidates 變數表示等候應徵的求職者,
用scores 變數表示他們對應的第一階段的分數。
(已知有7個應徵者)
程式如下:

candidates = ['Alice', 'Bob', 'Cindy', 'Daisy', 'Eve', 'Fairy', 'David'] 
scores = [74, 83, 73, 91, 80, 76, 89]
for i in range(7): #遍歷數字0,1,2,3,4,5,6
    print(candidates[i]+ ' 的分數為:', scores[i])
    if scores[i]<80: #如果求職者分數小於80分,跳過他
        continue
    print('恭喜 ' +candidates[i]+ ' 進入第二關面試')

結果:
Alice 的分數為: 74
Bob 的分數為: 83
恭喜 Bob 進入第二關面試
Cindy 的分數為: 73
Daisy 的分數為: 91
恭喜 Daisy 進入第二關面試
Eve 的分數為: 80
恭喜 Eve 進入第二關面試
Fairy 的分數為: 76
David 的分數為: 89
恭喜 David 進入第二關面試

舉一反三- break應用於while迴圈中

範例3: 韓信點兵- 三三數之剩二,五五數之剩三,七七數之剩二

「韓信點兵」是經典的數學問題,題意是說
韓信讓他的士兵三個排成一列會餘2個;
士兵每五個排成一列會餘3個;
士兵每七個排成一列會餘2個。
試問: 韓信最少有幾個士兵?

在數學上,有「中國剩餘定理」可以解這個問題,
如果我們不知道這個定理的話,
其實也是可以用程式暴力搜索解開的哦~

想法如下: 從正整數1開始檢查,
如果這個數字滿足「除以3餘2,除以5餘3,除以7餘2」條件,
就把這個數字印出來並跳出迴圈,
否則繼續檢查下一個正整數。
程式如下:

num = 1 #設定要檢查的數字的初始值
while True: # while True除非接收到break指令,否則迴圈永遠不會停下來
    if num%3 ==2 and num%5==3 and num%7==2: #取餘數的算術運算子是%
        #num本身是整數,必須用str()函數把num轉換成字串,才可以串接字串
        print('韓信最少有'+str(num)+'個士兵')
        break
    num+=1 

結果: 韓信最少有23個士兵
實際手算一下,23真的滿足「除以3餘2,除以5餘3,除以7餘2」條件。

課後練習-千軍萬馬

又到了課後練習時間啦~
在範例三中,已知目測韓信的士兵大約有500~1000人左右,
那麼韓信可能有多少士兵呢?
請嘗試修改範例3的程式,印出所有可能的結果。
print的部分請改成

print('韓信可能有'+str(num)+'個士兵')

歡迎在留言區留下你的答案交流討論哦~
進階思考: 你能不能只用while迴圈和if判斷式,而不用break指令完成呢?

【超進階版】首次有讓高手練習的問題來囉~ (本問題適合對python足夠熟悉者作答,新手可直接略過此部分。)考慮這邊是新手教學區,欲作答討論或詢問答案可直接私訊,並註記是在【python 超入門】(8)文章中看到的問題,本馬會跟您討論。
(1)給python好手的挑戰: 用任何你知道的python語法都行,你能否在三行以內解開呢?
(2)給python高高手的超進階挑戰: 你能否只用一行程式完成呢?
(注意你的答案中必須包括print('韓信可能有'+str(num)+'個士兵')以印出結果)


2
dylanliu
iT邦新手 5 級 ‧ 2019-07-05 17:44:01
num = 500 #設定要檢查的數字的初始值
while 500<= num <=1000: # while True除非接收到break指令,否則迴圈永遠不會停下來
   if num%3 ==2 and num%5==3 and num%7==2: #取餘數的算術運算子是%
      #num本身是整數,必須用str()函數把num轉換成字串,才可以串接字串
      print('韓信可能有'+str(num)+'個士兵')
   num+=1     

Bingo~ 恭喜答對,成功不用break語法解開了,讚讚~

1
harutsuki
iT邦新手 5 級 ‧ 2019-07-08 18:22:32
for num in range(500, 1000):
    if num%3==2 and num%5==3 and num%7==2:
        print('韓信最少有'+str(num)+'個士兵')

Bingo~ 這個也是正解,用for迴圈加range函數確實更簡潔呢~

0
harutsuki
iT邦新手 5 級 ‧ 2019-07-24 17:37:50
num_list = [f'韓信最少有{i}個士兵' for i in range(500, 1000) if i%3==2 and i%5==3 and i%7==2]
print(*num_list, sep="\n")  
0
harutsuki
iT邦新手 5 級 ‧ 2019-07-24 17:39:40
print("\n".join([f'韓信最少有{i}個士兵' for i in range(500, 1000) if i%3==2 and i%5==3 and i%7==2]))
2
harutsuki
iT邦新手 5 級 ‧ 2019-07-24 17:45:56
[print(f'韓信最少有{i}個士兵') for i in range(500, 1000) if i%3==2 and i%5==3 and i%7==2]

哇~ 高手是你~ 你的三個解答,把小馬心目中的精簡解答都寫出來了呢~

我要留言

立即登入留言