Я хотел бы перейти от естественно написанного списка строк к списку Python.

Примеры входных данных:

s1 = 'make the cake, walk the dog, and pick-up poo.'
s2 = 'flour, egg-whites and sand.'

Выход:

split1 = ['make the cake', 'walk the dog', 'pick-up poo']
split2 = ['flour', 'egg-whites', 'sand']

Я хочу разделить строки на запятые (и точки), «и» и «или», удалив при этом разбиения и пустые строки. Из-за отсутствия стандартизации в использовании оксфордской запятой я не могу просто разделить на запятые.

Я пробовал следующее:

import re
[x.strip() for x in re.split('([A-Za-z -]+)', s1) if x not in ['', ',', '.']]

Который дает:

['make the cake', 'walk the dog', 'and pick-up poo']

Что близко. Но для s2 это дает:

['flour', 'egg-whites and sand']

Я могу выполнить некоторую пост-обработку между элементами, чтобы непрерывно разделять элементы по (and|or), но я действительно хотел бы токенизировать набор запятых, и, и или.

Я пробовал несколько причудливых разделений регулярных выражений, чтобы иметь негативный взгляд на что-то вроде and, но он не хочет разбивать это слово.

[x.strip() for x in re.split('([A-Za-z -]+(?!and))', s2) if x not in ['', ',', '.']]
[x.strip() for x in re.split('([A-Za-z -]+(?!\band\b))', s2) if x not in ['', ',', '.']]

Что также дает

['flour', 'egg-whites and sand']

Я понимаю, что есть много крайних случаев, но мне кажется, что я близок и просто упускаю что-то маленькое.

1
nfmcclure 24 Ноя 2020 в 04:26

2 ответа

Лучший ответ

Ты можешь использовать

\s*(?:\b(?:and|or)\b|[,.])\s*

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

  • \s* - 0+ пробелов
  • (?:\b(?:and|or)\b|[,.]) - либо целое слово and, либо or, либо запятая / точка
  • \s* - 0+ пробелов

См. демонстрацию Python:

import re
rx = re.compile(r"\s*(?:\b(?:and|or)\b|[,.])\s*")
strings = ["make the cake, walk the dog, and pick-up poo.", "flour, egg-whites and sand."]
for s in strings:
    print( list(filter(None, rx.split(s))) )

Обратите внимание, что запятая или точка часто «исключаются», если они следуют за цифрами или заключаются в них, вы можете подумать о замене [.,] на [,.](?!\d) или [,.](?!(?<=\d[,.])\d).

2
Wiktor Stribiżew 24 Ноя 2020 в 01:31

Я думаю, вам нужно обрабатывать это по ходу:

  • применить разделение по пунктуации
  • применить расщепление по союзу

Это будет работать в обоих тестовых случаях, которые вы предоставили

1
topgunner 24 Ноя 2020 в 01:34
64978990