בדוק אם מחרוזת מכילה מספר ב-Python

מבוא

בין אם אתה בונה סקריפט אימות לקלט משתמש, טופס התחברות המבקש מהמשתמשים לכלול תו בסיסמה - בדיקה אם מחרוזת מכילה תו אינה פעולה נדירה.

במדריך זה – נסקור את הדרכים הרבות שבהן ניתן לבדוק האם מחרוזת מכילה ספרה/מספר ב-Python, כולל אמת מידה לגישה היעילה ביותר בסופו של דבר.

בדוק אם המחרוזת מכילה מספר ב-Python

ישנן מספר דרכים לבדוק אם א אופי הוא מספר (ord(), isnumeric(), isdigit()), שאתה יכול לשלב עם for-loop, כדי לבדוק לפחות פגיעה אחת חיובית. לחלופין, אתה יכול להשתמש בביטויים רגולריים כמתאמי דפוסים כלליים, שהם גמישים, חזקים ומיועדים ליישום על גופי טקסט גדולים. סוף סוף - אתה תמיד יכול map() כל דמות קיבלה הצהרה מותנית, והחזרה True is any() מהם מביאים True.

הבחירה בין אלה צריכה לקחת בחשבון את היעילות של השיטות, מידת המלל וסגנון הקידוד, כמו גם משימות במעלה הזרם או במורד הזרם הקשורות לפעולה.

בדוק אם המחרוזת מכילה מספר עם ord()

השמיים ord() הפונקציה לוקחת תו ומחזירה שלו ASCII ערך:

print(ord('0')) 
print(ord('9')) 

ערך ASCII של 0 הוא 48, וערך ASCII של 9 הוא 57. כל מספר בין אלה, יהיה בהרחבה, בעלי ערך ASCII בין 48 ל-57. עכשיו כדי לבדוק אם למחרוזת יש מספר כלשהו, ​​נחצה את כל מחרוזת הקלט ונבדוק את ערך ה-ASCII של כל תו, אם ערך ה-ASCII הוא יותר מ-47 וקטן מ-58, זה אומר שזה מספר, ונחזור True:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    ascii_code = ord(ch)
    if 47 < ascii_code < 58:
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

זו התוצאה:

Yes, the string contains a number.

בדוק אם המחרוזת מכילה מספר עם isnumeric()

השמיים isnumeric() פונקציה חוזרת True אם מחרוזת הקלט מכילה רק מספרים, אחרת, היא חוזרת False:

str1 = "918"
print("String is whole numeric?", str1.isnumeric())
str2 = "The meaning of the universe is 42"
print("String is whole numeric?", str2.isnumeric())

זו התוצאה:

String is whole numeric? True 
String is whole numeric? False

הערה: השמיים isnumeric() הפונקציה לא תתנהג כפי שאתה עשוי לצפות מספרים שליליים או צפים. אם נעביר מחרוזת עם מספרים שליליים או צפים בלבד, היא תחזור False, בגלל ה - ו . תווים הקשורים למספרים שליליים ולצפים הם אכן, לא מספרים.

str1 = "-918"
print("String is whole numeric?", str1.isnumeric()) 

str2 = "91.8"
print("String is whole numeric?", str2.isnumeric()) 

עם זאת, מכיוון שתווים הם רק מחרוזות באורך 1 ב- Python - אתה יכול לחזור על התווים ולהשתמש isnumeric() כדי לבדוק אם הם מספר:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    if ch.isnumeric():
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

בדוק אם המחרוזת מכילה מספר עם isdigit()

השמיים isdigit() הפונקציה בודקת אם כל התווים במחרוזת הם ספרות. אם כן - זה חוזר True, ואם לא, זה חוזר False. שוב, מכיוון שתווים הם רק מחרוזות באורך 1 ב- Python - ניתן להשתמש בשיטה זו בלולאה עבור כל תו:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    if ch.isdigit():
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

הערה: השמיים isdigit() השיטה מתנהגת רק באותו אופן כמו isnumeric(), ואם אתה מעביר אליה מחרוזת המכילה צף או מספר שלילי, False מוחזר בגלל שהתווים המיוחדים אינם מספרים. אבל ברמת הדמות, אם זה ארוך כמו אחד True הערך מספיק כדי לקבוע אם המחרוזת מכילה מספר - זה ישים.

ההבדל בין isnumeric() ל-isdigit()?

אז מה ההבדל בין isnumeric() ו isdigit()? בזמן שאנחנו בזה - מה לגבי isdecimal()?

  • isnumeric() בודק אם תו כלשהו הוא א ייצוג יוניקוד של ערך מספרי (שכוללת ייצוגים מספריים רומאים, כתוביות עיליות, כתוביות משנה ושברים)
  • isdigit() בודק אם תו כלשהו הוא א ספרת יוניקוד (שלא כולל ייצוגים מספריים רומאים, אבל כן כולל סופר/חתימות ושברים)
  • isdecimal() בודק אם תווים כלשהם הם א ספרה עשרונית (שהיה חוזר False לכל דבר שלא 0..9 בבסיס 10)

isnumeric() היא השיטה הרחבה ביותר, בעוד isdecimal() הוא הצר ביותר בין השלושה.

בדוק אם המחרוזת מכילה מספר עם map() וכל()

השמיים map() function מבצעת את הפונקציה שסופקה עבור כל רכיב של האיטרבל המועבר בפונקציית המפה. כל רכיב של איטרבל מועבר לפונקציה כפרמטר:

map(function, iterable)

השמיים function מבוצע עבור כל פריט של iterable. זה מאפשר הגיון גמיש ועוצמתי מאוד, מוגבל רק על ידי הרחבה של ה function אתה קורא על הקלט! השיטה מחזירה א map מופע, שניתן להפוך בקלות לאוספים אחרים כגון רשימה או סט.

אנחנו יכולים לכתוב פונקציה שמחזירה בוליאנית המייצגת אם תו הוא מספר, ואת map() call יביא לפיכך רשימה של ערכים בוליאניים.

השמיים any() החזרות True אם רכיב כלשהו של החזרה שעברה הוא True, אחרת, הוא חוזר False.

חיבור שני אלה יחד - נוכל ליצור תסריט קצר ברמה גבוהה ולהפשט את ה-for-loop משם:

def func(ch):
    return ch.isdigit() 

input_string = "My name is Satyam & I am 22 yrs old"
contains_number = any(list(map(func, input_string)))
print("Is there a number present?", contains_number)

זו התוצאה:

Is there a number present? True

אם הפונקציה שלך היא one-liner - אין צורך לחלץ אותה כפונקציה בעלת שם. אתה יכול לכתוב אנונימי פונקצית למבדה במקום זאת למען הקיצור:

עיין במדריך המעשי והמעשי שלנו ללימוד Git, עם שיטות עבודה מומלצות, סטנדרטים מקובלים בתעשייה ודף רמאות כלול. תפסיק לגוגל פקודות Git ולמעשה ללמוד זה!

input_string = "My name is Satyam & I am 22 yrs old"
contains_number = any(list(map(lambda ch: ch.isdigit(), input_string)))
print("Is there any number present?", contains_number)

זה גם מביא ל:

Is there any number present? True

בדוק אם המחרוזת מכילה מספר ב-Python עם ביטויים רגולריים

ביטויים רגולריים הם דפוסי חיפוש תוכנן להתאים לטקסט קלט. הם גמישים ובהתחשב באופי שלהם - אתה יכול לכתוב מספר שרירותי של ביטויים עבור אותו דפוס לחיפוש, כמו גם לכסות כל דפוס נסבל שאתה יכול לחשוב עליו.

פיתון re מודול משמש לכתיבה, קומפילציה והתאמת טקסט מול ביטויים רגולריים. הוא חושף שיטות שונות, כגון match() שתואם אם מחרוזת מתחילה בתבנית, search() אשר מוצא את המופע הראשון של אולי התאמות רבות במחרוזת, ו findall() שבודק את כל ההתרחשויות.

הערה: כל שלוש השיטות מקבלות את א pattern ו search טיעון והפעל חיפוש עבור ה pattern ב search מחרוזת.

התבנית המזהה את א ספרה is "d+":

import re
input_string = "My name is Satyam & I am 22 yrs old"
match = re.search(r"d+", input_string)
if match:
    print("Is there any number present?", "Yes")
else:
    print("Is there any number present?", "No")

השמיים search() שיטה מחזירה א re.Match אובייקט, המכיל את ההתאמה שנמצאה ואת מדדי ההתחלה והסיום:


ניתן להעריך את האובייקט לערך בוליאני בהתבסס על אם הוא א re.Match חפץ או None. זו התוצאה:

Is there any number present? Yes

בניגוד ל search() שיטה, findall() השיטה מחזירה את כל המופעים של התבנית במקום רק הראשונה:

import re
input_string = "My name is Satyam & I am 22 yrs old"
match = re.findall(r"d+", input_string)
if match:
    print("Is there any number present?", "Yes")
else:
    print("Is there any number present?", "No")

זו התוצאה:

Is there any number present? Yes

Benchmarking

מה עם הביצוע? אם אתה מחלץ את ההיגיון וחותך את החלקים המיותרים, מגביל את השיטות להחזרת התוצאה בלבד, אתה יכול בקלות לסמן אותן אחת מול השנייה באותו קלט:

%timeit ord_check()
%timeit isnumeric_check()
%timeit is_digit_check()
%timeit lambda_check()
%timeit regex_check()

זו התוצאה:

2.18 µs ± 51.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
2.04 µs ± 639 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
1.88 µs ± 448 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
5.07 µs ± 915 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
1.47 µs ± 3.41 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

בדרך כלל, גישות ה-for-loop פועלות בערך באותו זמן, עם מעט תקורה מהשיטות הספציפיות. למדה עם any() הוא למעשה האיטי ביותר (הרבה פעולות מיותרות, עקב המרת רשימה לרשימה ואז הקטנתה), בעוד ל-Regular Expressions היה זמן הריצה המהיר ביותר עם השונות הנמוכה ביותר סביבו (הם מהירים באופן עקבי).

עם זאת, בטקסטים ארוכים יותר של קלט, מורכבות הזמן בכל אחת מהגישות השונות מודגשת, במיוחד בהתאם למספר הספרות המותאמות (בין אם הספרות נפוצות או לא):

import random
import string

input_string_random = ''.join(random.choices(string.ascii_uppercase + string.digits, k=1000))
print(input_string_random) 

input_string_with_single_digit = ''.join(random.choices(string.ascii_uppercase, k=1000)) + '1'
print(input_string_with_single_digit) 

המחרוזת הראשונה יוצרת רצף אקראי עם מספר שווה של ספרות ותווים, בעוד שהאחרון הוא מחרוזת תווים בלבד עם ספרה בודדת בסופו של דבר (מורכבות הזמן הגרועה ביותר):

%timeit ord_check(input_string_random)
504 ns ± 22.6 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit ord_check(input_string_with_single_digit)
76.2 µs ± 1.36 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit isnumeric_check(input_string_random)
756 ns ± 170 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit isnumeric_check(input_string_with_single_digit)
76.2 µs ± 8.43 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit is_digit_check(input_string_random)
549 ns ± 102 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit is_digit_check(input_string_with_single_digit)
65 µs ± 20.6 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit lambda_check(input_string_random)
114 µs ± 8.77 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit lambda_check(input_string_with_single_digit)
119 µs ± 6.23 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit regex_check(input_string_random)
996 ns ± 19.8 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit regex_check(input_string_with_single_digit)
22.2 µs ± 1.77 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

עם מספר נמוך של להיטים - ביטויים רגילים הם הביצועיים ביותר. עם הרבה להיטים, גישת פונקציית למבדה היא הביצועית ביותר, והיא שומר על מורכבות הזמן שלו ללא קשר לשאלה אם לקלט יש הרבה כניסות או אחת. החיסרון העיקרי (חישוב מיותר כאשר קצב הפגיעה נמוך) הופך לחוזק העיקרי שלו מכיוון שהיתירות הופכת אותו לחזק לקלט.

סיכום

במדריך זה, בדקנו מספר דרכים לבדוק אם מחרוזת ב-Python מכילה לפחות תו אחד. בדקנו את ord(), isnumeric(), isdigit() ו isdecimal() פונקציה, כמו גם כיצד להפשט את ההיגיון הזה עם קריאת פונקציה למבדה באמצעות map() ו any(). לאחר מכן, חקרנו ביטויים רגולריים וסמנו את הגישות עם קלט משתנה.

בול זמן:

עוד מ Stackabuse