Як я можу перевірити, чи містить рядок БУДЬ-ЯКІ літери алфавіту?


86

Яка найкраща реалізація чистого Python для перевірки, чи містить рядок БУДЬ-ЯКІ літери з алфавіту?

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

Куди string_1б повернутися Falseза відсутність літер алфавіту в ньому і string_2повернувся б Trueза наявність літери.


2
Чи слід це обмежувати лише англійським a / z алфавітом? Чи слід враховувати "спеціальні" символи з інших алфавітів, таких як німецький?
— Котч

Чи є шанс, що ви отримаєте Unicode? Або просто прості букви ascii римські?
— KobeJohn

Хороший час там :) У будь-якому випадку, перевірте це подібне запитання, якщо вам потрібна допомога при тестуванні рядків із символами Unicode.
— KobeJohn

1
Обмежено лише англійським алфавітом a / z та лише простими латинськими літерами ascii :)
— Justin Papez

Відповіді:


125

Regex повинен бути швидким підходом:

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

1
Дякую JBernado, це те, що я в підсумку зробив, і це працює бездоганно для того, що мені потрібно зробити.
— Джастін Папес

37
Regex, безумовно, здається трохи надмірним. any(c.isalpha() for c in string_1)смачно пітонічна.
— Jollywatt

5
@ Джозеф Ні, це не так. Цей регулярний вираз набагато читабельніший, ніж ваш вираз. Крім того, що взагалі isalphaозначає? Це буде мати абсолютно різну поведінку при порівнянні Python 2 з Python 3. Чи є китайська частина алфавіту? Якщо ні, ви сліпо узгоджуєте його зі своїм генератором на Python 3 (або Python 2 для рядків Unicode!). Якщо ви хочете віщий , ось це: Simple is better than complex.. І перевірте коментар OP вище: Він хоче, щоб збігався лише римський алфавіт.
— JBernardo

1
Я думаю, що відповідь Джозефа цілком читається, і це, звичайно, швидше, ніж додатковий імпорт; плюс вам не потрібно пам’ятати порядок аргументів у повторних пошуках
— Хінтон,

11
Якщо хтось ще задається питанням, що таке повернене значення, ви отримуєте Matchоб’єкт, якщо є збіг або Noneякщо його немає. Отже, це сумісно з if re.search(...малюнком.
— Сріні

78

Як щодо:

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

Було set(string_1)б ефективніше?
— Rik Poggi

1
@Rik. Ви маєте на увазі перетворення рядка_1 в набір перед тестуванням? Ні, це не буде ефективніше. Це гарантовано матиме справу з усіма символами принаймні один раз, поки я вважаю, що будь-яка функція буде коротко замикатися (зупинятися), коли зустріне перше помилкове.
— KobeJohn

Цей код буде дещо повільним, оскільки вимагає виклику функції на символ. Перетворення setможе зменшити або не знизити виклики функцій, але додає трохи накладних витрат.
— JBernardo

2
@JBernardo: timeit припускає, що це приблизно на порядок повільніше, ніж скомпільований регулярний вираз, і займає лише приблизно на 66% більше часу, ніж нескладений. Це цілком відповідає моїм "Я ненавиджу регулярні вирази".
— DSM

1
Звичайно: і якщо ви використовуєте "(555) .555-5555 ext. 5555" * 1000, ви повертаєтеся до порівнянних швидкостей через коротке замикання. Я набагато більше люблю писати на Python, ніж писати регулярні вирази, які мені важко налагоджувати, якщо вони не є тривіальними, і я не збираюся відмовлятися від написання чіткого Python, якщо цього не вимагають вимоги до продуктивності.
— DSM

27

Ви можете використовувати islower()свій рядок, щоб перевірити, чи містить він деякі малі літери (серед інших символів). orце, isupper()щоб також перевірити, чи містить деякі великі літери:

внизу: літери в рядку: тест дає true

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

внизу: у рядку немає літер: тест дає помилку.

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

Не можна змішувати з isalpha()поверненнями Trueлише в тому випадку, якщо всі символи - букви, а це не те, що потрібно

Зверніть увагу, що Барм завершує мою, оскільки моя погано справляється зі змішаним відмінком.


3
Мені подобається, що це перевірить, чи містить він літери, а не просто перевіряє, чи вводяться ВСІ букви.
— Cornbeetle,

@Cornbeetle так, такий тип дійсно відповідає на питання після всіх цих років, дякую
— Жан-Франсуа Фабр

Дуже хороший спосіб це сказати. Як це з точки зору ефективності? краще, ніж регулярний вираз?
— pnv

тут не задіяні петлі python, тому ефективність хороша. Я не порівнював із регулярним виразом, але, гадаю, це трохи швидше, спеціально для фази ініціалізації, тому що регулярного
— Жан-Франсуа Фабр

13

Мені сподобалась відповідь, надана @ jean-françois-fabre , але вона є неповною.
Його підхід спрацює, але лише якщо текст містить суто малі чи великі літери:

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

Кращий підхід - спочатку прописати рядок у верхньому чи нижньому регістрі, а потім перевірити.

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

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

8

Ви можете використовувати такий регулярний вираз:

import re

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

2

Я протестував кожен із наведених вище методів, щоб з’ясувати, чи містяться в даному рядку якісь алфавіти, і з’ясував середній час обробки на рядок на стандартному комп’ютері.

~ 250 нс для

import re

~ 3 мкс для

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

~ 6 мкс для

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

~ 850 нс для

string.upper().isupper()


На відміну від передбачуваного, імпорт re займає незначний час, а пошук за допомогою re займає приблизно половину часу порівняно з ітерацією isalpha () навіть для відносно невеликого рядка.
Отже, для більших рядків і більших відліків re буде значно ефективнішим.

Але перетворення рядка у регістр і перевірка регістру (тобто будь-який з верхнього (). Isupper () або нижнього (). Islower () ) виграє тут. У кожному циклі це значно швидше, ніж re.search (), і навіть не потрібно додаткового імпорту.


1
Ви також можете скласти регулярний вираз для подальшої оптимізації. alpha_regex = re.compile ('[a-zA-Z]') пізніше alpha_regex.search (рядок)
— Бехдад Форгані

Не кажучи вже про те, що isalpha () погано тренується для багатьох мов. Я шукав це, тому що хотів перевірити, чи містить рядок, котрий, як очікується, корейська, англійські літери, а метод isalpha () повертає True для кожного корейського рядка.
— Чан Ву

0

Ви також можете зробити це додатково

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

Також зверніть увагу, що якщо змінна val повертає None. Це означає, що пошук не знайшов відповідності

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.