ValueError: слишком много значений для распаковки (ожидается 3) - Regex Matching - Python - PullRequest
0 голосов
/ 09 июля 2020

В моем коде Python у меня есть строка, и я пытаюсь найти, содержит ли строка определенный c шаблон (имя (я) после номера). Для этого я использую re.match, затем groups(), чтобы получить требуемый результат, подобный этому.

authors_and_year = re.match('(.*)\. (\d{4})\.', line)
texts, authors, year = authors_and_year.groups()

поэтому, если у меня есть такая строка

Regina Barzilay and Lillian Ли. 2004. Поймать смещение: модели содержания Probabilisti c с приложениями для генерации и обобщения. В материалах NAACL-HLT.

Он вернет мне это ( Как ожидалось );

('Regina Barzilay and Lillian Lee. 2004.', 'Regina Barzilay and Lillian Lee', '2004')

Но в некоторых случаях у меня есть строки вот так;

Дж. Коэн. 1968a. Взвешенная каппа: Соглашение по номинальной шкале с резервом на случай масштабного несогласия или частичного кредита. том 70, страницы 213–220

или это;

Ральф Вайшедель, Цзиньси Сюй и Ана Ликуанан. 1968b. Гибридный подход к ответам на биографические вопросы. В Mark Maybury, редакторе New Directions In Question Answering, глава 5. AAAI Нажмите

Где Год имеет алфавит, , поэтому верхнее регулярное выражение здесь не удалось . И чтобы справиться с этим сценарием, я пытаюсь добавить с ним новое регулярное выражение следующим образом:

authors_and_year = re.match('((.*)\. (\d{4})\.|(.*)\. (\d{4})(a-z){1}\.)', line)
texts, authors, year = authors_and_year.groups()

Но это дает мне эту ошибку;

ValueError: слишком много значений распаковать (ожидается 3)

Когда я проверил authors_and_year значение, было так:

('Regina Barzilay and Lillian Lee. 2004.', 'Regina Barzilay and Lillian Lee', '2004', None, None, None)

Я не знаю, откуда последние 3 None значения идут. Может ли кто-нибудь подсказать мне, что я здесь делаю не так ??

Ответы [ 2 ]

2 голосов
/ 09 июля 2020

Ваше регулярное выражение может быть уменьшено до этого ((.*)\.[ ](\d{4})[a-z]?\.) что делает письмо после года необязательным, сохраняя при этом 3 группы захвата.

1 голос
/ 09 июля 2020

Так работают группы с |. None s исходит от второй альтернативы. См .:

>>> re.match('(foo)|(bar)', 'foo').groups()
('foo', None)
>>> re.match('(foo)|(bar)', 'bar').groups()
(None, 'bar')

Вы можете отфильтровать несоответствия:

>>> [group for group in re.match('(foo)|(bar)', 'foo').groups() if group is not None]
['foo']
>>> [group for group in re.match('(foo)|(bar)', 'bar').groups() if group is not None]
['bar']

Или вы можете использовать именованные группы:

>>> match = re.match('(?P<first>foo)|(?P<second>bar)', 'foo')
>>> res = match.groupdict()["first"] or match.groupdict()["second"]
>>> res
'foo'
>>> match = re.match('(?P<first>foo)|(?P<second>bar)', 'bar')
>>> res = match.groupdict()["first"] or match.groupdict()["second"]
>>> res
'bar'

Этот код не будет работать, если возможны пустые совпадения (группа = пустая строка); вам нужно сделать что-то вроде

...
res = match.groupdict()["first"]
if res is None:
    res = match.groupdict()["second"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...