ตรวจสอบว่าสตริงมีตัวเลขใน 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() ตรวจสอบว่าตัวละครใด ๆ ที่เป็น a การแสดงยูนิโค้ด ของ ค่าตัวเลข (ซึ่งรวมถึงการแสดงตัวเลขโรมัน ตัวยก ตัวห้อย และเศษส่วน)
  • isdigit() ตรวจสอบว่าตัวละครใด ๆ ที่เป็น a ตัวเลขยูนิโค้ด (ซึ่งไม่รวมการแสดงตัวเลขโรมัน แต่รวมซุปเปอร์/ตัวห้อยและเศษส่วน)
  • isdecimal() ตรวจสอบว่ามีอักขระใดเป็น a หรือไม่ เลขฐานสิบ (ซึ่งจะกลับมา. False เพื่ออะไรก็ตามที่ไม่ใช่ 0..9 ในฐาน 10)

isnumeric() เป็นวิธีการที่กว้างที่สุดในขณะนั้น isdecimal() แคบที่สุดระหว่างทั้งสาม

ตรวจสอบว่าสตริงมีตัวเลขพร้อม map() และ any()

พื้นที่ map() ฟังก์ชั่น ดำเนินการฟังก์ชั่นที่ให้มาสำหรับแต่ละองค์ประกอบของการวนซ้ำที่ส่งผ่านในฟังก์ชั่นแผนที่ แต่ละองค์ประกอบของ iterable จะถูกส่งผ่านไปยังฟังก์ชันเป็นพารามิเตอร์:

map(function, iterable)

พื้นที่ function ถูกดำเนินการสำหรับทุกรายการของ iterable. สิ่งนี้ช่วยให้เกิดตรรกะที่ยืดหยุ่นและทรงพลังมาก โดยมีขอบเขตเพียงขอบเขตของความกว้างขวางเท่านั้น function คุณโทรเข้า! วิธีการส่งกลับค่า map ซึ่งสามารถเปลี่ยนเป็นคอลเลกชันอื่นๆ เช่น รายการหรือชุดได้อย่างง่ายดาย

เราสามารถเขียนฟังก์ชันที่คืนค่าบูลีนเพื่อแสดงว่าอักขระนั้นเป็นตัวเลขหรือไม่ และ map() การเรียกจะส่งผลให้เกิดรายการค่าบูลีน

พื้นที่ 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

หากฟังก์ชันของคุณเป็นแบบซับเดียว คุณไม่จำเป็นต้องแยกฟังก์ชันดังกล่าวเป็นฟังก์ชันที่มีชื่อ คุณสามารถเขียนแบบไม่ระบุชื่อได้ ฟังก์ชันแลมบ์ดา แทนเพื่อความกระชับ:

ดูคู่มือเชิงปฏิบัติสำหรับการเรียนรู้ Git ที่มีแนวทางปฏิบัติที่ดีที่สุด มาตรฐานที่ยอมรับในอุตสาหกรรม และเอกสารสรุปรวม หยุดคำสั่ง Googling 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 ด้วยนิพจน์ทั่วไปหรือไม่

นิพจน์ทั่วไปคือ รูปแบบการค้นหา ออกแบบมาให้จับคู่กับข้อความที่ป้อน พวกมันมีความยืดหยุ่นและเป็นไปตามธรรมชาติ คุณสามารถเขียนสำนวนจำนวนเท่าใดก็ได้สำหรับรูปแบบเดียวกันเพื่อค้นหา และยังครอบคลุมรูปแบบที่เข้าใจได้ง่ายที่คุณนึกออกด้วย

Python ของ re โมดูลนี้ใช้ในการเขียน คอมไพล์ และจับคู่ข้อความกับนิพจน์ทั่วไป โดยจะเผยวิธีการต่างๆ เช่น match() ซึ่งจับคู่ว่าสตริงขึ้นต้นด้วยรูปแบบหรือไม่ search() ซึ่งค้นหาการเกิดขึ้นครั้งแรกของรายการที่ตรงกันหลายรายการในสตริง และ findall() ซึ่งจะตรวจสอบเหตุการณ์ทั้งหมด

หมายเหตุ ทั้งสามวิธียอมรับ a 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() วิธีการคืนค่า a 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

เปรียบเทียบ

แล้วประสิทธิภาพล่ะ? หากคุณแยกตรรกะและตัดส่วนที่ไม่จำเป็นออก โดยจำกัดวิธีการส่งคืนผลลัพธ์เท่านั้น คุณสามารถเปรียบเทียบระหว่างกันในอินพุตเดียวกันได้อย่างง่ายดาย:

%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() defacto ช้าที่สุด (การดำเนินการซ้ำซ้อนจำนวนมาก เนื่องจากการแปลงรายการเป็นรายการแล้วลดขนาดลง) ในขณะที่นิพจน์ทั่วไปมีรันไทม์ที่เร็วที่สุดโดยมีความแปรปรวนน้อยที่สุด (รวดเร็วสม่ำเสมอ)

อย่างไรก็ตาม ในการป้อนข้อความที่ยาวขึ้น ความซับซ้อนของเวลาในแต่ละวิธีที่แตกต่างกันจะถูกเน้น โดยเฉพาะอย่างยิ่งขึ้นอยู่กับจำนวนหลักที่ตรงกัน (ไม่ว่าตัวเลขจะเป็นตัวเลขร่วมหรือไม่ก็ตาม):

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)

ด้วยจำนวนการเข้าชมที่น้อย – นิพจน์ทั่วไปจึงมีประสิทธิภาพมากที่สุด ด้วยการเข้าชมจำนวนมาก วิธีฟังก์ชัน lambda จึงมีประสิทธิภาพมากที่สุด และมันก็เป็นเช่นนั้น ยังคงความซับซ้อนของเวลาไว้ ไม่ว่าอินพุตจะมี Hit จำนวนมากหรือหนึ่งรายการก็ตาม ข้อเสียเปรียบหลัก (การคำนวณซ้ำซ้อนเมื่ออัตราการเข้าชมต่ำ) กลายเป็นจุดแข็งหลัก เนื่องจากความซ้ำซ้อนทำให้อินพุตมีความแข็งแกร่ง

สรุป

ในบทช่วยสอนนี้ เราได้ดูหลายวิธีในการตรวจสอบว่าสตริงใน Python มีอักขระอย่างน้อยหนึ่งตัวหรือไม่ เราได้ดูที่ ord(), isnumeric(), isdigit() และ isdecimal() ตลอดจนวิธีสรุปตรรกะนี้ด้วยการเรียกใช้ฟังก์ชัน lambda map() และ any(). จากนั้น เราได้สำรวจนิพจน์ทั่วไปและเปรียบเทียบแนวทางด้วยอินพุตที่แตกต่างกัน

ประทับเวลา:

เพิ่มเติมจาก สแต็ค