Python регулярное выражение для разделения строк, который заканчивается числами в скобках
У меня есть список, который генерируется после операции BeautifulSoup. У него есть строки, разделенные числами в скобках, которые я хочу разделить как внутренний список. Например у меня
L1=['alpha(1) beta(4)','delta(5) gamma(6)']
Это должно быть преобразовано в
[[‘alpha’, ‘beta’],[‘gamma’, ‘delta’]]
Я начал с этого
[re.split(r'\(\d\)',item) for item in L1]
но это создает дополнительное пространство в последнем элементе, а затем создает еще один элемент пробела в конце.
[['alpha', ' beta', ''], ['delta', ' gamma', '']]
Поэтому я добавляю еще одну строку в код, как это
L1=[re.split(r'\(\d\)',item) for item in L1]
[[x.strip() for x in y if x] for y in L1]
и это дает то, что я хочу
[['alpha', 'beta'], ['delta', 'gamma']]
Так что мои вопросы
- Почему он делает то, что делает, используя только первую строку команды. Почему этот последний элемент создан.
- Есть ли лучший способ достичь этого с помощью простого и простого регулярного выражения?
4 ответа
Из документов, re.split()
ведет себя идентично str.split()
и документы для str.split()
прямо заявить
Разделение пустой строки указанным разделителем возвращает [''].
Так как в правой части вашего разделителя есть пустая строка, вы получаете пустую строку в split()
результат. Я думаю, что идея возвращения ''
для строки emtpy приводит к более последовательному и предсказуемому поведению.
Что касается лучшего способа реализации вашего кода, я думаю, что следующее немного яснее:
>>> L1=['alpha(1) beta(4)','delta(5) gamma(6)']
>>> name_list = []
>>> for s in L1:
name_list.append(re.findall(r'(\w+)\(\d+\)', s))
>>> name_list
[['alpha', 'beta'], ['delta', 'gamma']]
или используя понимание списка:
name_list = [re.findall(r'(\w+)\(\d+\)', s) for s in L1]
Я бы использовал split:
print([[j.split("(")[0] for j in i.split()] for i in L1])
Возвращает:
[['alpha', 'beta'], ['delta', 'gamma']]
\(\d\)
шаблон находит несколько непересекающихся совпадений в вашей строке и разбивает строку в этих местах. Это означает, что это расщепляется 'alpha(1) beta(4)'
в alpha
, beta
и пустая строка с момента последнего (4)
стоит между beta
и конец строки.
Если вы хотите использовать регулярное выражение с оригинальным re.split
подход, вы можете рассмотреть возможность использования filter
чтобы избавиться от пустых элементов в результирующем списке:
import re
L1=['alpha(1) beta(4)','delta(5) gamma(6)']
res = [filter(None, re.split(r'\(\d+\)\s*', item)) for item in L1]
print(res)
# => [['alpha', 'beta'], ['delta', 'gamma']]
Посмотрите демо Python. \(\d+\)\s*
будет соответствовать цифры в скобках и \s*
будет соответствовать 0+ пробелам.
Разделите запятые, а затем используйте регулярные выражения для замены скобок и цифр. Наконец разделить строку на пробелы.
import re
>>> [re.sub('\(\d\)', '', y).split() for x in L1 for y in x.split(',')]
[['alpha', 'beta'], ['delta', 'gamma']]