Làm cách nào để kiểm tra xem một chuỗi có chứa BẤT KỲ chữ cái nào từ bảng chữ cái hay không?


82

Triển khai Python thuần túy tốt nhất là gì để kiểm tra xem một chuỗi có chứa BẤT KỲ chữ cái nào từ bảng chữ cái không?

string_1 = "(555).555-5555"
string_2 = "(555) 555 - 5555 ext. 5555

Nơi string_1sẽ trở lại Falsenếu không có chữ cái trong bảng chữ cái trong đó và string_2sẽ trở lại Truenếu có chữ cái.


2
Điều này có nên giới hạn trong bảng chữ cái a / z tiếng Anh không? Có nên tính đến các ký tự 'đặc biệt' từ các bảng chữ cái khác, chẳng hạn như tiếng Đức?
Kotch

Có cơ hội nào mà bạn nhận được unicode không? Hay chỉ là những chữ cái la mã ascii đơn giản?
KobeJohn,

Tốt thời gian ở đó :) Dù sao, hãy kiểm tra câu hỏi tương tự này nếu bạn cần trợ giúp kiểm tra chuỗi với các ký tự unicode.
KobeJohn,

1
Giới hạn trong tiếng Anh một bảng chữ cái / z chỉ và chỉ có chữ đơn giản ascii roman :)
Justin Papez

Câu trả lời:


123

Regex nên là một cách tiếp cận nhanh chóng:

re.search('[a-zA-Z]', the_string)

1
Cảm ơn JBernado, đây là những gì tôi đã làm và nó hoạt động hoàn hảo cho những gì tôi cần làm.
Justin Papez,

30
Regex chắc chắn có vẻ hơi quá mức cần thiết. any(c.isalpha() for c in string_1)là Pythonic ngon.
Jollywatt

5
@Joseph Không, không phải vậy. Biểu thức regex này dễ đọc hơn nhiều so với biểu thức của bạn. Ngoài ra, isalphathậm chí có nghĩa là gì? Điều này sẽ có những hành vi hoàn toàn khác khi so sánh Python 2 với Python 3. Tiếng Trung có phải là một phần của bảng chữ cái không? Nếu không, bạn đang khớp nó một cách mù quáng với trình tạo của bạn trên Python 3 (Hoặc Python 2 cho chuỗi unicode!). Nếu bạn muốn Pythonic , ở đây nó là: Simple is better than complex.. Và kiểm tra bình luận của OP ở trên: Anh ấy muốn chỉ bảng chữ cái la mã được khớp.
JBernardo

1
Tôi nghĩ câu trả lời của Joseph hoàn toàn có thể đọc được và nó chắc chắn nhanh hơn một lần nhập bổ sung; cộng với việc bạn không cần phải nhớ thứ tự của các đối số trong re.search
Hinton

11
Trong trường hợp bất kỳ ai khác thắc mắc giá trị trả về là gì, bạn sẽ nhận được một Matchđối tượng nếu có đối tượng khớp hoặc Nonenếu không có. Vì vậy, điều này tương thích với một if re.search(...mẫu.
Srini

74

Làm thế nào về:

>>> string_1 = "(555).555-5555"
>>> string_2 = "(555) 555 - 5555 ext. 5555"
>>> any(c.isalpha() for c in string_1)
False
>>> any(c.isalpha() for c in string_2)
True

Sẽ set(string_1)hiệu quả hơn?
Rik Poggi,

1
@Rik. Ý bạn là chuyển đổi chuỗi_1 thành một tập hợp trước khi thử nghiệm nó? Không, nó sẽ không hiệu quả hơn. Điều đó được đảm bảo sẽ xử lý tất cả các ký tự ít nhất một lần trong khi tôi tin rằng bất kỳ hàm nào cũng sẽ ngắn mạch (dừng) khi nó gặp lỗi đầu tiên.
KobeJohn,

Mã này sẽ hơi chậm vì nó yêu cầu một lệnh gọi hàm trên mỗi ký tự. Việc chuyển đổi thành setcó thể có hoặc không làm giảm các lệnh gọi hàm, nhưng thêm một số chi phí.
JBernardo

2
@JBernardo: timeit gợi ý rằng nó chậm hơn về thứ tự cường độ so với regex đã biên dịch và chỉ mất khoảng 66% thời gian hơn so với bản không được biên dịch. Điều đó nằm trong giới hạn "Tôi ghét cụm từ thông dụng" của tôi.
DSM

1
Chắc chắn rồi: và nếu bạn sử dụng "(555) .555-5555 máy lẻ 5555" * 1000, bạn sẽ quay lại tốc độ tương đương do chập mạch. Tôi thích viết bằng Python hơn là viết các biểu thức chính quy, điều mà tôi thấy khó gỡ lỗi trừ khi chúng tầm thường và tôi sẽ không từ bỏ việc viết Python rõ ràng trừ khi các yêu cầu về hiệu suất yêu cầu.
DSM

27

Bạn có thể sử dụng islower()trên chuỗi của mình để xem nó có chứa một số chữ cái viết thường (trong số các ký tự khác) hay không. orisupper()cũng để kiểm tra xem có chứa một số chữ cái viết hoa không:

dưới đây: các chữ cái trong chuỗi: test cho kết quả true

>>> z = "(555) 555 - 5555 ext. 5555"
>>> z.isupper() or z.islower()
True

bên dưới: không có chữ cái nào trong chuỗi: thử nghiệm cho kết quả là false.

>>> z= "(555).555-5555"
>>> z.isupper() or z.islower()
False
>>> 

Không được trộn lẫn với isalpha()Truechỉ trả về nếu tất cả các ký tự là chữ cái, đó không phải là những gì bạn muốn.

Lưu ý rằng câu trả lời của Barm hoàn thành tốt câu trả lời của tôi, vì câu trả lời của tôi không xử lý tốt trường hợp hỗn hợp.


3
Tôi thích rằng điều này sẽ kiểm tra xem nó CÓ CHỨA các chữ cái hay không, chứ không chỉ kiểm tra xem đầu vào là TẤT CẢ các chữ cái.
Cornbeetle

@Cornbeetle vâng, loại đó thực sự trả lời câu hỏi sau ngần ấy năm, cảm ơn
Jean-François Fabre

Cách rất hay để đặt điều này. Nó như thế nào về mặt hiệu quả? tốt hơn regex?
pnv

không có vòng lặp python liên quan, vì vậy hiệu quả là tốt. Tôi không so sánh với regex nhưng tôi cho rằng nó nhanh hơn một chút, đặc biệt cho giai đoạn khởi tạo vì không có regex để biên dịch
Jean-François Fabre

13

Tôi thích câu trả lời do @ jean-françois-fabre cung cấp , nhưng nó chưa đầy đủ.
Cách tiếp cận của anh ấy sẽ hiệu quả, nhưng chỉ khi văn bản hoàn toàn chứa các chữ cái thường hoặc chữ hoa:

>>> text = "(555).555-5555 extA. 5555"
>>> text.islower()
False
>>> text.isupper()
False

Cách tốt hơn là trước tiên hãy viết hoa hoặc viết thường chuỗi của bạn và sau đó kiểm tra.

>>> string1 = "(555).555-5555 extA. 5555"
>>> string2 = '555 (234) - 123.32   21'

>>> string1.upper().isupper()
True
>>> string2.upper().isupper()
False

8

Bạn có thể sử dụng biểu thức chính quy như sau:

import re

print re.search('[a-zA-Z]+',string)

2

Tôi đã thử nghiệm từng phương pháp ở trên để tìm xem có bất kỳ bảng chữ cái nào được chứa trong một chuỗi nhất định hay không và tìm ra thời gian xử lý trung bình cho mỗi chuỗi trên một máy tính tiêu chuẩn.

~ 250 ns cho

import re

~ 3 µs cho

re.search('[a-zA-Z]', string)

~ 6 µs cho

any(c.isalpha() for c in string)

~ 850 ns cho

string.upper().isupper()


Trái ngược với như cáo buộc, việc nhập lại mất thời gian không đáng kể và tìm kiếm với lại chỉ mất khoảng một nửa thời gian so với việc lặp lại isalpha () ngay cả đối với một chuỗi tương đối nhỏ.
Do đó, đối với các chuỗi lớn hơn và số lượng lớn hơn, re sẽ hiệu quả hơn đáng kể.

Nhưng chuyển đổi chuỗi thành một trường hợp và kiểm tra trường hợp (tức là bất kỳ trong số trên (). Isupper () hoặc dưới (). Islower () ) sẽ thắng ở đây. Trong mọi vòng lặp, nó nhanh hơn đáng kể so với re.search () và thậm chí nó không yêu cầu bất kỳ lần nhập bổ sung nào.


1
Bạn cũng có thể biên dịch regex để tối ưu hóa furhter. alpha_regex = re.compile ('[a-zA-Z]') sau alpha_regex.search (string)
Behdad Forghani

Chưa kể isalpha () không hoạt động tốt cho đa ngôn ngữ. Tôi đang tìm kiếm điều này vì tôi muốn kiểm tra xem một chuỗi được mong đợi là tiếng Hàn có chứa bất kỳ chữ cái tiếng Anh nào không và phương thức isalpha () trả về True cho mọi chuỗi tiếng Hàn.
Chan Woo

0

Ngoài ra bạn cũng có thể làm điều này

import re
string='24234ww'
val = re.search('[a-zA-Z]+',string) 
val[0].isalpha() # returns True if the variable is an alphabet
print(val[0]) # this will print the first instance of the matching value

Cũng lưu ý rằng nếu biến val trả về Không có. Điều đó có nghĩa là tìm kiếm không tìm thấy kết quả phù hợp

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.