удалить цифры, выраженные по-разному перед ключевым словом - PullRequest
1 голос
/ 31 марта 2020

Я пытаюсь очистить числа в начале строки, за которыми следует ключевое слово. Это число может быть выражено как digit (1 2 3), ordinal number (1-й 2-й 3-й) или strings (один два три).

Идея состоит в том, чтобы сохранить все числа непосредственно перед ключевое слово Предположим, что ключевыми словами являются basic|main|foundation. Например, следующие числа сохраняются, потому что за ними следует ключевое слово basic:

'one two three basic', '1 2 3 basic', '1st 2nd 3rd basic'

С другой стороны, установка слова перед ключевым словом требует удаления чисел. Например, следующие цифры пропали, потому что за ними следует very, а не ключевое слово:

'one two three very basic', '1 2 3 very basic', '1st 2nd 3rd very basic'

Это пример ввода:

text=['one two three basic', '1 2 3 basic', '1st 2nd 3rd basic',
      'one two three very basic', '1 2 3 very basic', '1st 2nd 3rd very basic']

Это ожидаемые строки :

expected=['one two three basic', '1 2 3 basic', '1st 2nd 3rd basic',
          'very basic', 'very basic', 'very basic']

Я пробовал это до сих пор без желаемых результатов:

import re

text=['one two three basic', '1 2 3 basic', '1st 2nd 3rd basic',
      'one two three very basic', '1 2 3 very basic', '1st 2nd 3rd very basic']

for element in text:
    element = re.sub(
                 r'(^((?:\d+(?:(st|[rd]d|th))?\s+)+|(?:(one|two|three)+\s+)+))(?!(?:(basic|main|foundations)$))',
                 '',
                 element,
                 0,
                 re.IGNORECASE)

    print(element)

Заранее спасибо за вашу помощь

Ответы [ 2 ]

2 голосов
/ 31 марта 2020

Я предлагаю использовать

import re

text=['one two three basic', '1 2 3 basic', '1st 2nd 3rd basic',
      'one two three very basic', '1 2 3 very basic', '1st 2nd 3rd very basic']
num_list=['one','two','three']
keywords = ['basic','main','foundations']
dgt_part = r'\d+(?:st|[rn]d|th)?'
num_wrd_part = '(?:{})'.format( '|'.join(num_list) )
kwd_part = '|'.join(keywords)
rx = re.compile(r'\b(?=({0}(?:\s+{0})*|{1}(?:\s+{1})*))\1(?!\s+(?:{2})\b)\s*'.format(dgt_part, num_wrd_part, kwd_part), re.I)
print(rx.pattern)
for element in text:
    print( rx.sub('',  element) )

См. Python demo

Вывод:

one two three basic
1 2 3 basic
1st 2nd 3rd basic
very basic
very basic
very basic

Полученное регулярное выражение будет выглядеть следующим образом \b(?=(\d+(?:st|[rn]d|th)?(?:\s+\d+(?:st|[rn]d|th)?)*|(?:one|two|three)(?:\s+(?:one|two|three))*))\1(?!\s+(?:basic|main|foundations)\b)\s*, см. онлайн-демонстрацию . Основные моменты:

  • Шаблон состоит из частей динамически
  • Захватывающая группа в предвкушении и последующая обратная ссылка используются для эмуляции поведения группы atomi c (это: не поддерживается Python re)

Подробности

  • \b - граница слова
  • (?=(\d+(?:st|[rn]d|th)?(?:\s+\d+(?:st|[rn]d|th)?)*|(?:one|two|three)(?:\s+(?:one|two|three))*)) - положительный прогноз, который захватывает
    • \d+(?:st|[rn]d|th)?(?:\s+\d+(?:st|[rn]d|th)?)* - число di git, за которым следуют 0 или более повторений из 1+ пробелов, разделенных ди git числами
    • | - или
    • (?:one|two|three)(?:\s+(?:one|two|three))* - номер слова, за которым следуют 0 или более повторений из 1+ номеров слов, разделенных пробелами
  • \1 - значение, захваченное в группе 1
  • (?!\s+(?:basic|main|foundations)\b) - не соответствовать, если есть 0+ пробелов и одно из ключевых слов в целом слове
  • \s* - 0+ пробелов.
0 голосов
/ 31 марта 2020

С допущениями, которые я приведу ниже, вы можете использовать регулярное выражение:

\b(?:one two three|1 2 3|1st 2nd 3rd)\s+basic\b|(?<=\bone two three\s)\w+\s+basic\b|(?<=\b1 2 3 )\w+\s+basic\b|(?<=\b1st 2nd 3rd )\w+\s+basic\b

, которое не содержит групп захвата.

Демо

Допущения следующие:

  • Один из литералов 'one two three', '1 2 3' или 1st 2nd 3rd' должен совпадать;
  • одному из трех приведенных выше литералов может предшествовать другие символы;
  • , если после одного из трех литералов следует один или несколько пробелов, за которыми следует слово 'basic', возможно, после других символов, строка состоит из трех литералов, пробелов и 'basic' соответствует; и
  • слово, предшествующее 'basic', за которым следует один или несколько пробелов, за которыми следует 'break', сопоставляется, если после одного из трех приведенных выше литералов сразу следует один пробел, за словом, предшествующим 'break', следует один или больше пробелов, за которыми следует 'break'. Механизм регулярных выражений

Python выполняет следующие операции.

\b                    # match word break
(?:                   # begin non-cap grp
  one two three       # match string
  |                   # or
  1 2 3               # match string
  |                   # or
  1st 2nd 3rd         # match string
)                     # end non-cap grp                    
\s+                   # match 1+ spaces 
basic                 # match string
\b                    # match word break
|                     # or
(?<=\bone two three ) # match string in positive look-behind
\w+\s+                # match word, then 1+ spaces 
basic                 # match string
\b                    # match word break 
|                     # or
(?<=\b1 2 3 )         # match string in positive look-behind
\w+\s+                # match word, then 1+ spaces 
basic                 # match string
\b                    # match word break 
|                     # or
(?<=\b1st 2nd 3rd )   # match string in positive look-behind
\w+\s+                # match word, then 1+ spaces 
basic                 # match string
\b                    # match word break 

Регулярное выражение можно несколько упростить, если можно использовать некоторые другие механизмы регулярных выражений, частично из-за тот факт, что движок Python, очевидно, не поддерживает PCRE \K (грубо говоря, "забудь все, что соответствовало") или запросы вида (?<=a|bb), даже если чередование включает две строки фиксированной длины. (Python очевидно требует, чтобы они были одинаковой длины).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...