Kiểm tra xem chuỗi có chứa số trong Python không

Giới thiệu

Cho dù bạn đang xây dựng tập lệnh xác minh cho dữ liệu đầu vào của người dùng, biểu mẫu đăng nhập yêu cầu người dùng đưa ký tự vào mật khẩu – việc kiểm tra xem chuỗi có chứa ký tự không phải là thao tác hiếm gặp.

Trong hướng dẫn này - chúng ta sẽ xem xét nhiều cách để bạn có thể kiểm tra xem một chuỗi có chứa chữ số/số trong Python hay không, bao gồm cả điểm chuẩn cho cách tiếp cận hiệu quả nhất cuối cùng.

Kiểm tra xem chuỗi có chứa số trong Python không

Có nhiều cách để kiểm tra xem một tính cách là một số (ord(), isnumeric(), isdigit()), bạn có thể kết hợp với vòng lặp for để kiểm tra ít nhất một lần truy cập tích cực. Ngoài ra, bạn có thể sử dụng Biểu thức chính quy làm công cụ so khớp mẫu chung, linh hoạt, mạnh mẽ và được thiết kế để áp dụng cho khối văn bản lớn. Cuối cùng – bạn luôn có thể map() mỗi ký tự được đưa ra một câu lệnh có điều kiện và trả về True is any() trong số họ dẫn đến True.

Việc lựa chọn giữa những điều này nên xem xét hiệu quả của các phương pháp, mức độ chi tiết và kiểu mã hóa, cũng như các tác vụ ngược dòng hoặc xuôi dòng liên quan đến hoạt động.

Kiểm tra xem chuỗi có chứa số với ord()

Sản phẩm ord() hàm nhận một ký tự và trả về ký tự của nó ASCII giá trị:

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

Giá trị ASCII của 0 là 48 và giá trị ASCII của 9 là 57. Bất kỳ số nào trong số này, theo phần mở rộng, có giá trị ASCII trong khoảng từ 48 đến 57. Bây giờ để kiểm tra xem chuỗi có số nào không, chúng ta sẽ duyệt toàn bộ chuỗi đầu vào và kiểm tra giá trị ASCII của từng ký tự, nếu giá trị ASCII lớn hơn 47 và nhỏ hơn 58 thì có nghĩa là một số và chúng ta sẽ trả về 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.")

Kết quả này trong:

Yes, the string contains a number.

Kiểm tra xem chuỗi có chứa số với innumeric() không

Sản phẩm isnumeric() hàm trả về True nếu chuỗi đầu vào chỉ chứa số, ngược lại, nó trả về 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())

Kết quả này trong:

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

Lưu ý: Sản phẩm isnumeric() chức năng sẽ không hoạt động như bạn mong đợi đối với số âm hoặc số float. Nếu chúng ta chuyển một chuỗi chỉ có số âm hoặc số thực, nó sẽ trả về False, bởi vì -. các ký tự được liên kết với số âm và số float thực sự, không phải số.

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

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

Tuy nhiên, vì các ký tự chỉ là các chuỗi có độ dài 1 trong Python – bạn có thể lặp qua các ký tự và sử dụng isnumeric() để kiểm tra xem chúng có phải là số không:

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.")

Kiểm tra xem chuỗi có chứa số với isdigit()

Sản phẩm isdigit() Hàm kiểm tra xem tất cả các ký tự trong chuỗi có phải là chữ số hay không. Nếu có – nó sẽ trả về True, và nếu không, nó trả về False. Một lần nữa, vì các ký tự chỉ là các chuỗi có độ dài 1 trong Python – phương thức này có thể được sử dụng trong một vòng lặp cho mỗi ký tự:

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.")

Lưu ý: Sản phẩm isdigit() phương pháp chỉ hoạt động theo cách tương tự như isnumeric()và nếu bạn chuyển một chuỗi chứa số float hoặc số âm cho nó, False được trả về do các ký tự đặc biệt không phải là số. Tuy nhiên, ở cấp độ ký tự, nếu miễn là một True giá trị đủ để xác định xem chuỗi có chứa số hay không – nó có thể áp dụng được.

Sự khác biệt giữa isnumeric() và isdigit()?

Vì vậy, sự khác biệt giữa isnumeric()isdigit()? Trong khi chúng ta đang ở đó – thì sao isdecimal()?

  • isnumeric() kiểm tra xem có bất kỳ ký tự nào là một đại diện unicode của một giá trị số (bao gồm các biểu diễn số La Mã, chỉ số trên, chỉ số dưới và phân số)
  • isdigit() kiểm tra xem có bất kỳ ký tự nào là một chữ số unicode (không bao gồm các biểu diễn số La Mã, nhưng bao gồm siêu/chỉ số dưới và phân số)
  • isdecimal() kiểm tra xem có bất kỳ ký tự nào là một chữ số thập phân (mà sẽ trở lại False vì bất cứ điều gì không phải 0..9 ở cơ sở 10)

isnumeric() là phương pháp rộng nhất, trong khi isdecimal() là hẹp nhất giữa ba.

Kiểm tra xem chuỗi có chứa số với map() và any()

Sản phẩm map() chức năng thực thi chức năng được cung cấp cho từng thành phần của iterable được truyền trong chức năng bản đồ. Mỗi phần tử của một iterable được truyền cho hàm dưới dạng tham số:

map(function, iterable)

Sản phẩm function được thực hiện cho mọi mục của iterable. Điều này cho phép logic rất linh hoạt và mạnh mẽ, chỉ bị giới hạn bởi sự mở rộng của function bạn gọi vào đầu vào! Phương thức trả về một map ví dụ, có thể dễ dàng biến thành các bộ sưu tập khác như danh sách hoặc bộ.

Chúng ta có thể viết một hàm trả về một giá trị boolean cho biết một ký tự có phải là một số hay không và map() do đó, cuộc gọi sẽ dẫn đến một danh sách các giá trị boolean.

Sản phẩm any() Trả về True nếu bất kỳ phần tử nào của iterable đã qua là True, ngược lại, nó trả về False.

Kết hợp hai cái này lại với nhau - chúng ta có thể tạo một tập lệnh ngắn, cấp cao và trừu tượng hóa vòng lặp for:

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)

Kết quả này trong:

Is there a number present? True

Nếu hàm của bạn là một lớp - thì không cần phải trích xuất nó dưới dạng hàm được đặt tên. Bạn có thể viết một ẩn danh hàm lambda thay vào đó vì mục đích ngắn gọn:

Xem hướng dẫn thực hành, thực tế của chúng tôi để học Git, với các phương pháp hay nhất, các tiêu chuẩn được ngành công nghiệp chấp nhận và bảng lừa đảo đi kèm. Dừng lệnh Googling Git và thực sự học nó!

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)

Điều này cũng dẫn đến:

Is there any number present? True

Kiểm tra xem chuỗi có chứa số trong Python với biểu thức chính quy không

Biểu thức chính quy là mẫu tìm kiếm được thiết kế để phù hợp với văn bản đầu vào. Chúng linh hoạt và có tính chất riêng – bạn có thể viết số lượng biểu thức tùy ý cho cùng một mẫu để tìm kiếm, cũng như bao gồm bất kỳ mẫu dễ hiểu nào mà bạn có thể nghĩ ra.

Python's re mô-đun được sử dụng để viết, biên dịch và khớp văn bản với các biểu thức thông thường. Nó đưa ra nhiều phương pháp khác nhau, chẳng hạn như match() khớp với việc một chuỗi bắt đầu bằng một mẫu, search() tìm thấy lần xuất hiện đầu tiên của nhiều kết quả khớp trong một chuỗi và findall() kiểm tra tất cả các lần xuất hiện.

Lưu ý: Cả ba phương pháp đều chấp nhận một patternsearch đối số và chạy một tìm kiếm cho pattern trong search chuỗi.

Mẫu xác định một chữ số 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")

Sản phẩm search() phương thức trả về một re.Match đối tượng, chứa kết quả khớp được tìm thấy và các chỉ số bắt đầu và kết thúc:


Đối tượng có thể được đánh giá thành giá trị boolean dựa trên việc nó có phải là một re.Match đối tượng hoặc None. Kết quả này trong:

Is there any number present? Yes

Không giống như các search() phương pháp, findall() phương thức trả về tất cả các lần xuất hiện của mẫu thay vì chỉ lần đầu tiên:

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")

Kết quả này trong:

Is there any number present? Yes

Điểm chuẩn

Còn hiệu suất thì sao? Nếu bạn trích xuất logic và cắt bớt những phần không cần thiết, giới hạn các phương thức chỉ trả về kết quả, bạn có thể dễ dàng so sánh chúng với nhau trên cùng một đầu vào:

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

Kết quả này trong:

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)

Nói chung, các cách tiếp cận vòng lặp for chạy trong cùng một khoảng thời gian, với ít chi phí hoạt động từ các phương pháp cụ thể. Lambda với any() trên thực tế là chậm nhất (rất nhiều thao tác dư thừa, do chuyển đổi danh sách thành danh sách rồi giảm bớt), trong khi Biểu thức chính quy có thời gian chạy nhanh nhất với phương sai thấp nhất xung quanh nó (chúng luôn nhanh).

Tuy nhiên, trên các văn bản đầu vào dài hơn, độ phức tạp về thời gian của từng cách tiếp cận khác nhau được nhấn mạnh, đặc biệt tùy thuộc vào số lượng chữ số khớp (dù chữ số có phổ biến hay không):

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) 

Chuỗi đầu tiên tạo ra một chuỗi ngẫu nhiên có số lượng chữ số và ký tự bằng nhau, trong khi chuỗi sau là chuỗi chỉ có ký tự có một chữ số duy nhất ở cuối (độ phức tạp về thời gian tồi tệ nhất):

%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)

Với số lần truy cập thấp – Biểu thức chính quy có hiệu suất cao nhất. Với nhiều lần truy cập, cách tiếp cận hàm lambda là hiệu quả nhất và nó giữ lại độ phức tạp thời gian của nó bất kể đầu vào có nhiều lượt truy cập hay một lượt truy cập. Nhược điểm chính (tính toán dư thừa khi tỷ lệ trúng thấp) trở thành điểm mạnh chính của nó vì tính dư thừa khiến cho việc nhập liệu trở nên khó khăn.

Kết luận

Trong hướng dẫn này, chúng ta đã xem xét nhiều cách để kiểm tra xem một chuỗi trong Python có chứa ít nhất một ký tự hay không. Chúng tôi đã xem xét ord(), isnumeric(), isdigit()isdecimal() chức năng, cũng như cách trừu tượng hóa logic này bằng lệnh gọi hàm lambda bằng cách sử dụng map()any(). Sau đó, chúng tôi đã khám phá Biểu thức chính quy và đánh giá các phương pháp tiếp cận với đầu vào khác nhau.

Dấu thời gian:

Thêm từ xếp chồng lên nhau