8

Разделение строк на слова с использованием нескольких разделителей границ слов

1

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

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

Результат должен быть таким:

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

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

5 ответ(ов)

5

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

>>> 'a;bcd,ef g'.replace(';',' ').replace(',',' ').split()
['a', 'bcd', 'ef', 'g']

В данном примере мы заменяем все вхождения символов ; и , на пробелы, а затем используем метод split(), который разбивает строку на части по пробелам. В результате получаем нужный список строк.

5

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

Вот как выглядит код:

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']+" находит все последовательности символов, которые соответствуют словам (включая апострофы). Это позволяет удобно разделить текст на слова, что может быть полезно в различных задачах обработки текста. Важно отметить, что использование регулярных выражений в данном случае делает код более компактным и понятным.

0

Да, есть способ избавиться от знаков препинания без использования регулярных выражений. Вы можете сделать это, используя модуль 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(). В результате вы получите список слов без знаков препинания.

0

Совет-практика: Используйте 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()!

0

Если вы хотите разбить строку на части, используя несколько разделителей, и не планируете использовать модуль 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']

Теперь функция будет возвращать только непустые строки, что может улучшить качество вывода вашей функции.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь