檢查字串中是否有數字
檢查字串中是否有數字¶
使用 any() 與 isdigit()¶
Python 內建函數 any(), 可以檢查物件中是否有 True ,若有一個為 True,則回傳 True。
# 物件中有一個為 True
print(any([False, False, True, False]))
# 物件中全部為 False
print(any([False, False, False, False]))
True False
要判斷是否有數字,可以用函數 str.isdigit() ,如果字串全部為數字,則會回傳 True,反之,則回傳 False。 因此可以搭配 any() 函數,逐一抽取出字串中的字元,一一比對是否為數字,若有一個為數字,則回傳 True,而 any() 函數也會回傳 True。反之,都不為數字,則全為 False,any() 函數也會回傳 False。
str1 = "python3.7"
str2 = "NoNumber"
str3 = "1234567890"
print(any(char.isdigit() for char in str1))
print(any(char.isdigit() for char in str2))
print(any(char.isdigit() for char in str3))
True False True
使用 any() 、 map() 與 isdigit() 函數¶
map(function, iterable) 函數將函數 function 應用於物件中的每個元素,並且逐一回傳每個元素在被 function 處理過後的結果。
str1 = "python3.7"
str2 = "NoNumber"
str3 = "1234567890"
print(any(map(str.isdigit, str1)))
print(any(map(str.isdigit, str2)))
print(any(map(str.isdigit, str3)))
True False True
使用正規表達式¶
正規表達式當中 \d 代表數字 0 ~ 9 。
re.search(r"\d", string) 會搜尋字串 string 內符合數字的字元,並回傳相關資訊。若都不為數字,代表找不到數字,則回傳 None。
import re
match1 = re.search(r"\d", "python3.7")
print(match1)
match2 = re.search(r"\d", "NoNumber")
print(match2)
<re.Match object; span=(6, 7), match='3'> None
match 物件內有一個 span , span 有 2 個 tuple ,它們是 match 的開始和結束位置,索引值由 0 開始算。
匹配的內容則以 match 顯示,例如 match ='3'。
bool() 函數可以將 re.match object 或 None 的結果轉換為 True 或 False。
import re
str1 = "python3.7"
str2 = "NoNumber"
str3 = "1234567890"
print(bool(re.search(r"\d", str1)))
print(bool(re.search(r"\d", str2)))
print(bool(re.search(r"\d", str3)))
True False True
效能測試¶
import timeit
import re
# 待測試的函式 : 使用 any() 與 isdigit() 函數
def DetectNumber1(string):
return any(char.isdigit() for char in string)
# 待測試的函式 : 使用 any()、map() 與 isdigit() 函數
def DetectNumber2(string):
return any(map(str.isdigit, string))
# 待測試的函式 : 使用 正規表達式 與 bool() 函數
def DetectNumber3(string):
return bool(re.search(r"\d", str1))
# 待測試的函式 : 使用 正規表達式 與 compile() 函數
def DetectNumber4(string):
number = re.compile('\d')
return False if (number.search(string) == None) else True
# stmt 準備要測試的函數或語句,字串形式
# setup 執行的環境,本範例中表示 if __name__ == '__main__':
# number 被測試的函數或語句,執行的次數,
# 本範例表示執行 100,000 次 DetectNumber1()。預設值是 10,000 次
# 說明:此函數在 if __name__ == '__main__' 的條件下,
# 執行 100,000 次 DetectNumber1() 消耗的時間
t1 = timeit.timeit(stmt="DetectNumber1('HereNumber123')",
setup="from __main__ import DetectNumber1",
number=100000)
print("DetectNumber1():", t1)
t2 = timeit.timeit(stmt="DetectNumber2('HereNumber123')",
setup="from __main__ import DetectNumber2",
number=100000)
print("DetectNumber2():", t2)
t3 = timeit.timeit(stmt="DetectNumber3('HereNumber123')",
setup="from __main__ import DetectNumber3",
number=100000)
print("DetectNumber3():", t3)
t4 = timeit.timeit(stmt="DetectNumber4('HereNumber123')",
setup="from __main__ import DetectNumber4",
number=100000)
print("DetectNumber3():", t4)
DetectNumber1(): 0.12795189999997092 DetectNumber2(): 0.08853980000003503 DetectNumber3(): 0.10212330000013026 DetectNumber3(): 0.10813580000012735
小結:使用 any() 搭配迴圈取字元交給 isdigit 判斷的方式,速度最慢。而使用 any()、map() 與 isdigit 的判斷速度最快。兩種正規表達式的方法效能居中,本範例測試較短的字串,測試十萬次所得的平均結果。 接下來,我們用一篇短文做測試。看看效能如何?
import timeit
import re
document = "Yahoo Life Brooklyn Decker gets real about how photo " \
"editing makes imperfections disappear: It s all fake " \
"Kerry Justich " \
"Fri, April 2, 2021, 2:00 AM " \
"Brooklyn Decker is pulling back the curtain on the modeling" \
"industry and showing Instagram followers that it s all fake" \
"with a video showing the before and after of her retouched image." \
"The 33-year-old model and actress took to her social media to" \
"give a behind-the-scenes look at a photo of her while toggling " \
"between the photo s edited and unedited state to reveal the dark " \
"spots, wrinkles and visible veins that disappear with the help of " \
"Photoshop. Now how do I do that surgically. she joked. " \
"In the comments, people praised Decker for being so transparent." \
"Thank you so much for showing this! I am so self conscious about " \
"my neck, one person wrote, while another commented, Thanks for " \
"using your voice! I hope that a ton of young girls see this! " \
"Others reflected on how real the star is and begged to see " \
"more of this! For Decker, it isn t the first time that she s" \
"been unfiltered with her online audience."
# 待測試的函式 : 使用 any() 與 isdigit() 函數
def DetectNumber1(string):
return any(char.isdigit() for char in string)
# 待測試的函式 : 使用 any()、map() 與 isdigit() 函數
def DetectNumber2(string):
return any(map(str.isdigit, string))
# 待測試的函式 : 使用 正規表達式 與 bool() 函數
def DetectNumber3(string):
return bool(re.search(r"\d", str1))
# 待測試的函式 : 使用 正規表達式 與 compile() 函數
def DetectNumber4(string):
number = re.compile('\d')
return False if (number.search(string) == None) else True
t1 = timeit.timeit(stmt="DetectNumber1('" + document + "')",
setup="from __main__ import DetectNumber1",
number=100000)
print("DetectNumber1():", t1)
t2 = timeit.timeit(stmt="DetectNumber2('" + document + "')",
setup="from __main__ import DetectNumber2",
number=100000)
print("DetectNumber2():", t2)
t3 = timeit.timeit(stmt="DetectNumber3('" + document + "')",
setup="from __main__ import DetectNumber3",
number=100000)
print("DetectNumber3():", t3)
t4 = timeit.timeit(stmt="DetectNumber4('" + document + "')",
setup="from __main__ import DetectNumber4",
number=100000)
print("DetectNumber3():", t4)
DetectNumber1(): 0.9799677999999403 DetectNumber2(): 0.7449845000001005 DetectNumber3(): 0.10843560000012076 DetectNumber3(): 0.23524350000025152
小結:較長的短文,使用 any() 與 isdigit() 函數效能一樣最差。反倒原本效能最好的 any()、map()與 isdigit() 效能直線滑落,倒數第二名。而正規表達式兩種都表現不錯,其中 正規表達式 與 bool(),表現最為出色。
結論:當比較對象為小短字串時,例如:單字或較少的字串,使用 any()、map() 與 isdigit() 函數,效能最佳。如果要比較短文時,則是正規表達式與 bool() 函數表現最好。
Lai Tai-Yu (賴岱佑)
Comments
Post a Comment