Быстрый способ разделения буквенных и числовых символов в строке python

Я пытаюсь выработать простую функцию для захвата опечаток, например:

"Westminister15"
"Westminister15London"
"23Westminister15London"

после фиксации:

["Westminister", "15"]
["Westminister", "15", "London"]
["23", "Westminister", "15", "London"]

Первая попытка:

 def fixate(query):
     digit_pattern = re.compile(r'\D')
     alpha_pattern = re.compile(r'\d')
     digits = filter(None, digit_pattern.split(query))
     alphas = filter(None, alpha_pattern.split(query))
     print digits
     print alphas

результат:

 fixate("Westminister15London")

 > ['15']
 > ['Westminister', 'London']

Однако, я думаю, что это можно было бы сделать более эффективно, и я все равно получаю плохие результаты, когда я пытаюсь что-то вроде:

 fixate("Westminister15London England")

 > ['15']
 > ['Westminister', 'London England']

Очевидно, что он должен заинтриговать London и England отдельно, но я чувствую, что моя функция будет полностью исправлена ​​и более простой подход

Этот вопрос несколько эквивалентен этому php question

Ответ 1

Проблема в том, что Python re.split() не разбивается на совпадения нулевой длины. Но вы можете получить желаемый результат с помощью re.findall():

>>> re.findall(r"[^\W\d_]+|\d+", "23Westminister15London")
['23', 'Westminister', '15', 'London']
>>> re.findall(r"[^\W\d_]+|\d+", "Westminister15London England")
['Westminister', '15', 'London', 'England']

\d+ соответствует любому числу цифр, [^\W\d_]+ соответствует любому слову.

Ответ 2

Вот другой подход, если вы предпочитаете держаться подальше от регулярных выражений, что иногда может быть громоздким, если вы не достаточно знакомы, чтобы сделать это/изменить его сами:

from itertools import groupby

def split_text(s):
    for k, g in groupby(s, str.isalpha):
        yield ''.join(g)

print(list(split_text("Westminister15")))
print(list(split_text("Westminister15London")))
print(list(split_text("23Westminister15London")))
print(list(split_text("Westminister15London England")))

возвращает:

['Westminister', '15']
['Westminister', '15', 'London']
['23', 'Westminister', '15', 'London']
['Westminister', '15', 'London', ' ', 'England']

Генератор также может быть легко модифицирован, чтобы при желании никогда не выдавать пробельные строки.

Ответ 3

Вы можете использовать это регулярное выражение вместо своих:

>>> import re
>>> regex = re.compile(r'(\d+|\s+)')
>>> regex.split('Westminister15')
['Westminister', '15', '']
>>> regex.split('Westminister15London England')
['Westminister', '15', 'London', ' ', 'England']
>>> 

Затем вам нужно отфильтровать список, удаляющий пустые строки/только пробелы.