Разделить строку на знаки препинания или числа в Python

Я пытаюсь разделить строки каждый раз, когда встречаю знак препинания или цифры, например:

toSplit = 'I2eat!Apples22becauseilike?Them'
result = re.sub('[0123456789,.?:;~!@#$%^&*()]', ' \1',toSplit).split()

Желаемый результат:

['I', '2', 'eat', '!', 'Apples', '22', 'becauseilike', '?', 'Them']

Однако приведенный выше код (хотя он правильно разбивается там, где должен) удаляет все цифры и знаки препинания.

Мы будем очень признательны за любые разъяснения.


person patri    schedule 14.08.2019    source источник
comment
Попробуйте re.findall(r'\d+|[^\w\s]|_|[^\W\d_]+', toSplit)   -  person Wiktor Stribiżew    schedule 14.08.2019
comment
Итак, если есть строка типа 11!!, вам нужно получить ['11', '!!'], верно?   -  person Wiktor Stribiżew    schedule 14.08.2019
comment
Да, именно так. Я еще не пробовал этот случай, спасибо, что указали на это :)   -  person patri    schedule 14.08.2019
comment
Затем вы можете обобщить решение, используя re.findall(r'\d+|(?:[^\w\s]|_)+|[^\W\d_]+', toSplit) для токенизации цифр, букв и других символов, которые не являются пробелами, буквами и цифрами. Интересно, что бы вы хотели сделать с 22.45text?!...   -  person Wiktor Stribiżew    schedule 14.08.2019


Ответы (3)


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

re.findall(r'\d+|(?:[^\w\s]|_)+|[^\W\d_]+', toSplit)

Здесь,

  • \d+ - 1+ цифры
  • (?:[^\w\s]|_)+ - 1+ символов кроме слов и пробельных символов или _
  • [^\W\d_]+ - любые 1+ буквы Unicode.

См. демонстрацию регулярного выражения.

Подход сопоставления является более гибким, чем разделение, поскольку он также позволяет токенизировать сложную структуру. Скажем, вы также хотите токенизировать десятичные (с плавающей запятой, двойные...) числа. Вам просто нужно будет использовать \d+(?:\.\d+)? вместо \d+:

re.findall(r'\d+(?:\.\d+)?|(?:[^\w\s]|_)+|[^\W\d_]+', toSplit) 
             ^^^^^^^^^^^^^

См. эту демонстрацию регулярного выражения.

person Wiktor Stribiżew    schedule 14.08.2019

Используйте re.split с группой захвата:

toSplit = 'I2eat!Apples22becauseilike?Them'
result = re.split('([0-9,.?:;~!@#$%^&*()])', toSplit)
result

Выход:

['I', '2', 'eat', '!', 'Apples', '2', '', '2', 'becauseilike', '?', 'Them']

Если вы хотите разделить повторяющиеся числа или знаки препинания, добавьте +:

result = re.split('([0-9,.?:;~!@#$%^&*()]+)', toSplit)
result

Выход:

['I', '2', 'eat', '!', 'Apples', '22', 'becauseilike', '?', 'Them']
person Chris    schedule 14.08.2019
comment
Благодарю вас! Ты спасатель! :) - person patri; 14.08.2019

Используйте re.split для разделения всякий раз, когда найден диапазон алфавита

>>> import re                                                              
>>> re.split(r'([A-Za-z]+)', toSplit)                                      
['', 'I', '2', 'eat', '!', 'Apples', '22', 'becauseilike', '?', 'Them', '']
>>>                                                                        
>>> ' '.join(re.split(r'([A-Za-z]+)', toSplit)).split()                    
['I', '2', 'eat', '!', 'Apples', '22', 'becauseilike', '?', 'Them']        
person Sunitha    schedule 14.08.2019