Разделение строк на слова с использованием нескольких разделителей границ слов
Я считаю, что то, что я хочу сделать, является довольно распространенной задачей, но я не нашел никаких ссылок в интернете. У меня есть текст с пунктуацией, и я хочу получить список слов.
"Hey, you - what are you doing here!?"
Результат должен быть таким:
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']
Но метод str.split()
в Python работает только с одним аргументом, и после разбиения по пробелу у меня остаются слова с пунктуацией. Есть идеи, как решить эту проблему?
5 ответ(ов)
Другой быстрый способ сделать это без использования регулярных выражений — сначала заменить символы, как показано ниже:
>>> 'a;bcd,ef g'.replace(';',' ').replace(',',' ').split()
['a', 'bcd', 'ef', 'g']
В данном примере мы заменяем все вхождения символов ;
и ,
на пробелы, а затем используем метод split()
, который разбивает строку на части по пробелам. В результате получаем нужный список строк.
В данном примере регулярные выражения оправданы, поскольку они позволяют эффективно извлекать слова из строки, игнорируя при этом знаки препинания.
Вот как выглядит код:
import re
DATA = "Hey, you - what are you doing here!?"
print(re.findall(r"[\w']+", DATA))
# Выводит: ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']
Регулярное выражение r"[\w']+"
находит все последовательности символов, которые соответствуют словам (включая апострофы). Это позволяет удобно разделить текст на слова, что может быть полезно в различных задачах обработки текста. Важно отметить, что использование регулярных выражений в данном случае делает код более компактным и понятным.
Да, есть способ избавиться от знаков препинания без использования регулярных выражений. Вы можете сделать это, используя модуль string
и списковое выражение, как показано ниже:
import string
punc = string.punctuation # Получаем все знаки препинания
thestring = "Hey, you - what are you doing here!?"
# Преобразуем строку в список символов и фильтруем знаки препинания
result = ''.join([char for char in thestring if char not in punc]).split()
print(result)
Этот код проходит по каждому символу в строке и добавляет его в новый список, только если он не является знаком препинания. Затем мы объединяем символы в строку и разбиваем её на слова, используя метод split()
. В результате вы получите список слов без знаков препинания.
Совет-практика: Используйте string.translate
для самых быстрых операций со строками в Python.
Несколько доказательств...
Сначала медленный способ (извини, pprzemek):
>>> import timeit
>>> S = 'Эй, ты - что ты здесь делаешь!?'
>>> def my_split(s, seps):
... res = [s]
... for sep in seps:
... s, res = res, []
... for seq in s:
... res += seq.split(sep)
... return res
...
>>> timeit.Timer('my_split(S, punctuation)', 'from __main__ import S,my_split; from string import punctuation').timeit()
54.65477919578552
Теперь используем re.findall()
(как предложено в ответе). ГОРАЗДО быстрее:
>>> timeit.Timer('findall(r"\w+", S)', 'from __main__ import S; from re import findall').timeit()
4.194725036621094
И, наконец, используем translate
:
>>> from string import translate, maketrans, punctuation
>>> T = maketrans(punctuation, ' '*len(punctuation))
>>> timeit.Timer('translate(S, T).split()', 'from __main__ import S,T,translate').timeit()
1.2835021018981934
Объяснение:
string.translate
реализован на C и, в отличие от многих функций манипуляции строками в Python, string.translate
не создаёт новую строку. Поэтому это почти самый быстрый способ замены строк.
Это немного неудобно, так как для этого необходимо создать таблицу перевода. Вы можете сделать таблицу перевода с помощью удобной функции maketrans()
. Цель тут — заменить все нежелательные символы на пробелы. Один к одному. Снова, никаких новых данных не создаётся. Поэтому это быстро!
Затем используем старый добрый split()
. split()
по умолчанию работает со всеми пробельными символами, группируя их вместе для разделения. Результат будет списком слов, который вам нужен. И этот подход почти в 4 раза быстрее, чем re.findall()
!
Если вы хотите разбить строку на части, используя несколько разделителей, и не планируете использовать модуль re
, вы можете реализовать функцию, как показано в вашем примере. Ваша функция my_split
принимает строку s
и список разделителей seps
, и последовательно выполняет разбиение строки по каждому из этих разделителей.
Вот ваш код с некоторыми пояснениями:
def my_split(s, seps):
res = [s] # Начинаем с одной строки в результате
for sep in seps: # Проходим по каждому разделителю
s, res = res, [] # Переписываем s из res и обнуляем res
for seq in s:
res += seq.split(sep) # Разделяем каждую последовательность по текущему разделителю
return res # Возвращаем список разбитых элементов
print(my_split('1111 2222 3333;4444,5555;6666', [' ', ';', ',']))
# ['1111', '', '2222', '3333', '4444', '5555', '6666']
В результате выполнения функции my_split
, строка '1111 2222 3333;4444,5555;6666'
разбивается на отдельные элементы по заданным разделителям (' '
, ';'
, ','
). Обратите внимание, что в результате появляются пустые строки, которые возникают из-за нескольких пробелов между числами.
Если вы хотите избежать пустых строк в выводе, можно слегка изменить финальную часть функции, фильтруя результат:
def my_split(s, seps):
res = [s]
for sep in seps:
s, res = res, []
for seq in s:
res += seq.split(sep)
return [item for item in res if item] # Убираем пустые строки
print(my_split('1111 2222 3333;4444,5555;6666', [' ', ';', ',']))
# ['1111', '2222', '3333', '4444', '5555', '6666']
Теперь функция будет возвращать только непустые строки, что может улучшить качество вывода вашей функции.
Разделить строку по пробелам в Python
Вывод строки в текстовый файл
Как заполнить строку в Python пробелами?
Диапазон букв в Python
Как создать строку с разделением запятой из списка строк?