разделить строку на строку и цифры

#python #regex

#python #регулярное выражение

Вопрос:

Я пытаюсь разделить эту строку ( incoming_string ) на цифры и строку на следующий вид ( result ):

incoming_string = '02, 102, 702New York' # Also possible incoming strings: '06, 25Jerusalem' or '34Saint Luise'

result = {'New York': ['02', '102', '702']}

Я нашел этот подход, но я думаю, что это не лучший способ:

 import re


digits = re.findall('d ', incoming_string)  # ['02', '102', '702']
strings = re.findall('[a-z, A-Z] ', incoming_string)[-1]  # 'New York'
  

Под наилучшим способом я подразумеваю наиболее краткий, понятный и pythonic способ, предпочтительный без импорта.
Все символы имеют одинаковую кодировку (ascii)

Комментарии:

1. Я думаю, что это довольно общее решение. Выглядит хорошо для меня. Просто создайте dict like {strings: digits} .

2. Не лучше ли в каком смысле, не могли бы вы определить, что вы ищете?

3. @SerialLazer самый краткий, понятный и pythonic способ, предпочтительнее без импорта

4. Вы будете иметь дело исключительно с буквами ASCII? Если нет, подумайте, что произойдет, например, для Saint-Étienne или любого другого имени с диакритическими знаками.

5. Без import re этого вы бы технически написали некоторую форму исходного кода регулярных выражений (хотя и специфичную для вашего варианта использования). Изобретать велосипед, особенно библиотеку, которая предоставляется и широко используется, — это огромный анти-шаблон, честно говоря.

Ответ №1:

Проблема заключается в поиске индекса, где заканчивается список и начинается значение ключа. Мы можем создать функцию, которая поможет нам найти первый «символ, не входящий в список». Затем нужно разделить строку на две части, используя этот индекс, после чего мы можем разделить первую часть на список, используя ", " разделитель.

 def get_first_non_list_char_index(incoming_string):
    for i, c in enumerate(incoming_string):
        if c not in "1234567890, ":
            return i

incoming_string = "02, 102, 702New York"
char_index = get_first_non_list_char_index(incoming_string)

result = {incoming_string[char_index:]: incoming_string[:char_index].split(", ")}
  

result = {'New York': ['02', '102', '702']}

Ответ №2:

Используйте это:

(d{2}), (d{3}), (d{3})(. )

ДЕМОНСТРАЦИЯ

Код:

 import re

incoming_string = '02, 102, 702New York'
print(re.sub("(d{2}), (d{3}), (d{3})(. )", "{\4: [\1, \2, \3]}", incoming_string))
  

вывод:

{New York: [02, 102, 702]}

Ответ №3:

import меньше решения по запросу:

 incoming_string = '02, 102, 702New York'
letters = ''.join(i for i in incoming_string if i.isalpha() or i.isspace())
numbers = ''.join(i for i in incoming_string if i.isdigit() or i.isspace())
result = {letters.strip(): numbers.split()}
print(result)
  

Вывод:

 {'New York': ['02', '102', '702']}
  

Ответ №4:

Вы можете использовать re.split для получения этого результата:

 sl=['02, 102, 702New York',  
'06, 25Jerusalem',
'34Saint Luise']

import re

for s in sl:
    fields=re.split(r'(?<=d)(?=[a-zA-Z])', s, maxsplit=1)
    print(s, "=>", {fields[1]:re.split(r',[ ]*',fields[0])})
  

С принтами:

 02, 102, 702New York => {'New York': ['02', '102', '702']}
06, 25Jerusalem => {'Jerusalem': ['06', '25']}
34Saint Luise => {'Saint Luise': ['34']}