Разбить строку Python по буквам и сохранить разделители - PullRequest
3 голосов
/ 04 ноября 2019

Используя регулярное выражение, как я могу разбить строку и сохранить ее разделители в возвращаемых результатах? Я пытаюсь разбить строку, содержащую числа и строки, на набор букв, за которыми следует любое числовое значение, включая «.»однако он не работает должным образом.

Ниже приведена моя тестовая строка, я использую python 2.7, и он не выдает ожидаемого идентификатора.

s = 'M160.394,83.962L121.5,52L86.31,73.378L58,104.917L89.75,C136.667L158.542,136.667L185,110.208L160.394,83.962Z'
parts = filter(None, re.split('([MLHVCSQTAZ][^MLHVCSQTAZ]+)', s, re.IGNORECASE))
print len(parts), parts
>>> 3 ['M160.394,83.962', 'L121.5,52', 'L86.31,73.378L58,104.917L89.75,C136.667L158.542,136.667L185,110.208L160.394,83.962Z']

Я ожидаю, что это даст мне это

>>> 10 ['M160.394,83.962', 'L121.5,52', 'L86.31,73.378', 'L58,104.917', 'L89.75,', 'C136.667', 'L158.542,136.667', 'L185,110.208', 'L160.394,83.962', 'Z']

Должен быть выведен список строк, каждая строка которых начинается с буквы, найденной в исходном регулярном выражении MLHVCSQTAZ

Ответы [ 3 ]

5 голосов
/ 04 ноября 2019

В вашем коде вы передаете re.IGNORECASE в качестве 3-го аргумента re.split, но 3-й аргумент re.split - это maxsplit, а не флаги.

re.IGNORECASE равно 2, следовательно, ваш вход разделен только два раза.

Вы можете использовать:

>>> list(filter(None, re.split(r'([MLHVCSQTAZ][^MLHVCSQTAZ]+)', s, 0, re.I)))
['M160.394,83.962', 'L121.5,52', 'L86.31,73.378', 'L58,104.917', 'L89.75,', 'C136.667', 'L158.542,136.667', 'L185,110.208', 'L160.394,83.962', 'Z']

Или использовать встроенный режим для игнорирования регистра:

re.split(r'(?i)([MLHVCSQTAZ][^MLHVCSQTAZ]+)', s)

Я предлагаю использовать этот простой re.findall код, который использует почти идентичное регулярное выражение:

parts = re.findall('(?i)[MLHVCSQTAZ][^MLHVCSQTAZ]*', s)

Ссылка: SRE_FLAG_IGNORECASE = 2 в lib/python2.7/sre_constants.py (спасибо комментарию от @VKS)

3 голосов
/ 04 ноября 2019
parts = filter(None, re.split('([MLHVCSQTAZ][^MLHVCSQTAZ]+)', s, flags=re.IGNORECASE))

Необходимо использовать определение функции flags .Check re.split.

По умолчанию re не поддерживает 0 width assertion split. Так что для этого также можно использовать модуль regex.

import regex
s = 'M160.394,83.962L121.5,52L86.31,73.378L58,104.917L89.75,C136.667L158.542,136.667L185,110.208L160.394,83.962Z'
print regex.split('(?=[MLHVCSQTAZ][^MLHVCSQTAZ])', s, flags=regex.IGNORECASE|regex.VERSION1)
3 голосов
/ 04 ноября 2019

Вы можете использовать re.findall:

import re
s = 'M160.394,83.962L121.5,52L86.31,73.378L58,104.917L89.75,C136.667L158.542,136.667L185,110.208L160.394,83.962Z'
result = re.findall('[A-Z][\.\d,]+|[A-Z]', s)

Выход:

['M160.394,83.962', 'L121.5,52', 'L86.31,73.378', 'L58,104.917', 'L89.75,', 'C136.667', 'L158.542,136.667', 'L185,110.208', 'L160.394,83.962', 'Z']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...