Разъяснение по регулярным выражениям Python и findall()

Я столкнулся с этой проблемой, когда работал над Python Challenge. Номер 10, если быть точным. Я решил попытаться решить эту проблему с помощью регулярных выражений — вытащить повторяющиеся последовательности, подсчитать их длину и построить следующий элемент последовательности на основе этого.

Итак, регулярное выражение, которое я разработал, было: '(\d)\1*'

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

regex = re.compile('(\d)\1*')
text = '111122223333'
re.findall(regex, text)

> ['1', '1', '1', '1', '2', '2', '2',...]

И так далее. Итак, я узнаю о необработанном типе в модуле re для Python. Каков мой первый вопрос: может кто-нибудь объяснить, что именно это делает? В документе это описано как уменьшение необходимости избегать обратной косой черты, но не похоже, что это требуется для более простых регулярных выражений, таких как \d+, и я не понимаю, почему.

Поэтому я меняю свое регулярное выражение на r'(\d)\1*' и теперь пытаюсь использовать findall(), чтобы составить список последовательностей. И я получаю

> ['1', '2', '3']

Опять очень запутался. Я до сих пор этого не понимаю. Помоги пожалуйста?

Я решил сделать это, чтобы обойти это:

[m.group() for m in regex.finditer(text)]
> ['1111', '2222', '3333']

И получить то, что я искал. Затем, основываясь на этом потоке, я пытаюсь findall() добавить группу в все регулярное выражение -> r'((\d)\2*)'. В итоге я получаю:

> [('1111', '1'), ('2222', '2'), ('3333', '3')]

В этот момент я вся в замешательстве. Я знаю, что этот результат как-то связан с несколькими группами, но я просто не уверен.

Кроме того, это моя первая публикация, поэтому я извиняюсь, если мой этикет неверен. Пожалуйста, не стесняйтесь поправить меня и в этом. Спасибо!


person Louis    schedule 23.07.2012    source источник
comment
Вы должны избегать объединения нескольких вопросов, подобных этому, это затрудняет их выполнение. Лучше размещать отдельные простые вопросы. Вы также должны указать, какого результата вы ожидали, вместо того, чтобы просто сказать, что вас смущает то, что вы получили.   -  person millimoose    schedule 23.07.2012
comment
Я столкнулся с этой проблемой... Я решил решить ее с помощью регулярных выражений... Сколько у вас сейчас проблем?   -  person Daniel Roseman    schedule 23.07.2012
comment
@DanielRoseman: для задач Python Challenge, задача 10, регулярные выражения — хороший способ решить эту проблему. Если вы понимаете, что на самом деле дает вам модуль re..   -  person Martijn Pieters    schedule 23.07.2012
comment
Сформулируйте вопрос. Укажите это в первой строке. Не заставляйте нас высиживать эссе и ссылаться на вопрос вне pythonchallenge. .com, поэтому нам нужно решить задачи 0..9, чтобы перейти к формулировке вашего вопроса. Гррр. Если вы хотите написать эссе о коде, разместите его в блоге. Этот сайт предназначен для вопросов и ответов. Не пишите, что я сделал X. Потом я прочитал Z. Итак, я попробовал Y. Я запутался. Вместо этого напишите, что я пытаюсь сделать A, результат должен выглядеть как B, почему код C вместо этого производит D?   -  person smci    schedule 16.01.2015


Ответы (1)


Поскольку это вызов, я не дам вам полный ответ. Однако вы на правильном пути.

Метод finditer возвращает MatchObject экземпляра. Вы хотите посмотреть на них .group() и прочитать документацию тщательно. Подумайте, какая там разница между .group(0) и .group(1); обычный .group() такой же, как .group(0).

Что касается escape-символа \d; поскольку эта конкретная escape-комбинация не имеет значения как escape-символ строки Python, Python игнорирует ее и оставляет в виде обратной косой черты и буквы d. Действительно, было бы лучше использовать строковый формат r'', так как это предотвратит неприятные сюрпризы, когда вы делаете хотите использовать набор символов регулярного выражения, который также является управляющей последовательностью, которую python распознает. Дополнительные сведения см. в документации Python по строковым литералам.

Ваш .findall() с выражением r'((\d)\2*)' возвращает 2 элемента за совпадение, поскольку у вас есть 2 группы в вашем шаблоне; внешняя группа, соответствующая (\d)\2*, и внутренняя группа, соответствующая \d. Из .findall() документации:

Если в шаблоне присутствует одна или несколько групп, вернуть список групп; это будет список кортежей, если шаблон имеет более одной группы.

person Martijn Pieters    schedule 23.07.2012
comment
Что вы имеете в виду, когда говорите, что эта спасательная комбинация не имеет смысла? Я все еще не понимаю этого. Распознается ли он как класс цифровых символов или нет? (когда вы не используете необработанный формат) - person Louis; 23.07.2012
comment
@Louis: он имеет значение как класс регулярного выражения, но не как escape-последовательность python (например, \n, это новая строка). - person Martijn Pieters; 23.07.2012
comment
@Мартин: Понятно, спасибо. Единственное, что ускользает от меня сейчас, это то, почему findall() дал второй результат, о котором я упоминал. - person Louis; 23.07.2012
comment
@Louis: Потому что в итоге у вас будет две группы соответствия: (\d)\2* и \d. - person JAB; 23.07.2012