Вопрос-Ответ

Split Strings into words with multiple word boundary delimiters

Разбиение строк на слова с несколькими разделителями границ слов

Я думаю, что то, что я хочу сделать, является довольно распространенной задачей, но я не нашел ссылок в Интернете. У меня есть текст с пунктуацией, и мне нужен список слов.

"Hey, you - what are you doing here!?"

должно быть

['hey', 'you', 'what', 'are', 'you', 'doing', 'here']

Но Python str.split() работает только с одним аргументом, поэтому у меня все слова с пунктуацией после разделения пробелом. Есть идеи?

Переведено автоматически
Ответ 1

re.split()


re.split(шаблон, строка[, maxsplit=0])


Разбивать строку по вхождениям шаблона. Если в шаблоне используются фиксирующие скобки, то текст всех групп в шаблоне также возвращается как часть результирующего списка. Если значение maxsplit ненулевое, происходит не более разделения maxsplit, и оставшаяся часть строки возвращается как последний элемент списка. (Примечание о несовместимости: в оригинальной версии Python 1.5 maxsplit игнорировался. Это было исправлено в более поздних версиях.)


>>> re.split('\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split('(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split('\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
Ответ 2

Случай, когда оправданы регулярные выражения:

import re
DATA = "Hey, you - what are you doing here!?"
print re.findall(r"[\w']+", DATA)
# Prints ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']
Ответ 3

Еще один быстрый способ сделать это без регулярного выражения - сначала заменить символы, как показано ниже:

>>> 'a;bcd,ef g'.replace(';',' ').replace(',',' ').split()
['a', 'bcd', 'ef', 'g']
Ответ 4

Так много ответов, но я не могу найти ни одного решения, которое эффективно выполняло бы то, о чем буквально просит заголовок вопросов (разделение по нескольким возможным разделителям — вместо этого многие ответы разделяются на все, что не является словом, что отличается). Итак, вот ответ на вопрос в названии, который основан на стандартном и эффективном модуле Python re:

>>> import re  # Will be splitting on: , <space> - ! ? :
>>> filter(None, re.split(r"[, \-!?:]+", "Hey, you-what are you doing here!?"))
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

где:


  • […]соответствует одному из разделителей, перечисленных внутри,

  • \- в регулярном выражении здесь используется для предотвращения специальной интерпретации - как индикатора диапазона символов (как в A-Z),

  • + пропускает один или несколько разделителей (это можно было бы опустить благодаря filter(), но это привело бы к ненужному образованию пустых строк между совпадающими односимвольными разделителями),

  • использование необработанной строки r"…" явно указывает, что \ в строке должно быть все как есть (и не вводится специальный символ) — это полезно для Python 3.12+-, и

  • filter(None, …) удаляет пустые строки, возможно, созданные начальными и конечными разделителями (поскольку пустые строки имеют логическое значение false).

Это re.split() точно "разбивается с несколькими разделителями", как указано в названии вопроса.

Кроме того, это решение невосприимчиво к проблемам с символами, отличными от ASCII, в словах, встречающимся в некоторых других решениях (см. Первый комментарий к ответу ghostdog74).

Модуль re намного эффективнее (по скорости и краткости), чем выполнение циклов Python и тестов "вручную"!

python string