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']]

Так что мои вопросы

  1. Почему он делает то, что делает, используя только первую строку команды. Почему этот последний элемент создан.
  2. Есть ли лучший способ достичь этого с помощью простого и простого регулярного выражения?

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']]
Другие вопросы по тегам