Как извлечь указанные c строки, используя Python Regex - PullRequest
3 голосов
/ 09 января 2020

У меня есть очень сложные струны, с которыми я боролся. Например,

str1 = '95% for Pikachu, 92% for Sandshrew'
str2 = '70% for Paras & 100% Arcanine'
str3 = '99% Diglett, 40% Dugtrio'
str4 = '10% Squirtle, 100% for Alakazam'
str5 = '30% Metopod & 99% Dewgong'

Строка начинается с % целое число и может иметь for или нет, затем следует имя покемона. Может быть знак comma(,) или &, а затем новое % целое число. Наконец, есть еще одно имя покемонов. (Все начинаются с заглавной буквы) Я хочу извлечь двух покемонов, например, результат:

['Pikachu', 'Sandshrew']
['Paras', 'Arcanine']
['Diglett', 'Dugtrio']
['Squirtle', 'Alakazam']
['Metopod', 'Dewgong']

Я могу создать список всех покеменов, используя синтаксис in, но это не лучший способ (в случае, если они добавляют больше покемонов) , Можно ли извлечь с помощью Regex? Заранее спасибо! EDIT По запросу я добавляю свой код,

str_list = [str1, str2, str3, str4, str5]

for x in str_list:
    temp_list = []
    if 'for' in x:
        temp = x.split('% for', 1)[1].strip()
        temp_list.append(temp)
    else:
        temp = x.split(" ", 1)[1]
        temp_list.append(temp)
print(temp_list)

Я знаю, что это не регулярное выражение express. Выражение, которое я пробовал, это \d+, чтобы извлечь целое число, чтобы начать ... но не знаю, как начать. EDIT2 @ b_ c имеет хороший край, поэтому я добавляю его сюда

edge_str = '100% for Pikachu, 29% Pika Pika Pikachu'

результат

['Pikachu', 'Pika Pika Pikachu']

Ответы [ 4 ]

2 голосов
/ 09 января 2020

Надеюсь, я не переусердствовал в этом, но я хотел охватить крайние случаи немного более сложных именованных покемонов, таких как "Мистер Мим", "Farfetch'd" и / или "Nidoran♂ "(только смотря на первые 151).

Я использовал шаблон (?:(?:\d+%(?: |for)+([A-Z](?:[\w\.♀♂']|(?: (?=[A-Z])))+))+)[, &]*, который, похоже, работает в моем тестировании (вот ссылка regex101 для разбивки).

Для общего резюме я ищу:

  • 1 + цифры, за которыми следует%
  • Пробел или слово "for" хотя бы один раз
  • (Для начала захвата) Начальная заглавная буква
  • Как минимум одно из (окончание группы захвата):
    • символ слова, точка, мужской / женский символы или апостроф
      • Примечание. Если вы хотите поймать дополнительные «странные» символы покемонов, такие как цифры, двоеточие и т. д. c., добавьте их в эту часть (бит [\w\.♀♂']).
    • ИЛИ пробел, но только , если за ним следует заглавная буква
  • Запятая, пробел или амперсан d, любое количество раз

Если это не изменено, встроенный Python модуль *1045* не поддерживает повторные группы захвата (что, я считаю, я сделал правильно), поэтому я просто использовал re.findall и организовал их в пары (я заменил пару имен из вашего ввода на сложные):

import re

str1 = '95% for Pikachu, 92% for Mr. Mime'
str2 = '70% for Paras & 100% Arcanine'
str3 = '99% Diglett, 40% Dugtrio'
str4 = "10% Squirtle, 100% for Farfetch'd"
str5 = '30% Metopod & 99% Nidoran♂'

pattern = r"(?:(?:\d+%(?: |for)+([A-Z](?:[\w\.♀♂']|(?: (?=[A-Z])))+))+)[, &]*"

# Find matches in each string, then unpack each list of
# matches into a flat list
all_matches = [match
               for s in [str1, str2, str3, str4, str5]
               for match in re.findall(pattern, s)]

# Pair up the matches
pairs = zip(all_matches[::2], all_matches[1::2])

for pair in pairs:
    print(pair)

Затем выведите:

('Pikachu', 'Mr. Mime')
('Paras', 'Arcanine')
('Diglett', 'Dugtrio')
('Squirtle', "Farfetch'd")
('Metopod', 'Nidoran♂')

Кроме того, как уже было упомянуто, у вас есть несколько опечаток в именах покемонов, но, к сожалению, регулярное выражение не подходит для этого:)

1 голос
/ 09 января 2020

Поскольку в ваших строках, похоже, нет заглавной буквы, вы можете просто использовать [A-Z]\w+ в качестве регулярного выражения. См. regex101

Код:

import re

str1 = '95% for Pikachu, 92% for Sandsherew'
str2 = '70% for Paras & 100% Arcanine'
str3 = '99% Diglett, 40% Dugtrio'
str4 = '10% Squirtle, 100% for Alakazam'
str5 = '30% Metopod & 99% Dewgong'

str_list = [str1, str2, str3, str4, str5]
regex = re.compile('[A-Z]\w+')
pokemon_list = []
for x in str_list:
    pokemon_list.append(re.findall(regex, x))
print(pokemon_list)

Выход:

[['Pikachu', 'Sandsherew'], ['Paras', 'Arcanine'], ['Diglett', 'Dugtrio'], ['Squirtle', 'Alakazam'], ['Metopod', 'Dewgong']]
0 голосов
/ 09 января 2020

Альтернативный метод, если вы не хотите использовать регулярные выражения и не хотите полагаться на заглавные буквы

def pokeFinder(strng):
    wordList = strng.split()
    pokeList = []
    for word in wordList:
        if not set('[~!@#$%^&*()_+{}":;\']+$').intersection(word) and 'for' not in word:
            pokeList.append(word.replace(',', ''))
    return pokeList

Это не добавит слова со специальными символами. Также не будут добавлены слова, которые for. Затем он удаляет запятые из найденных слов.

Печать str2 возвращает ['Diglett', 'Dugtrio']


РЕДАКТИРОВАТЬ В свете того факта, что, по-видимому, Pokemon с двумя словами и специальными символами, я сделал эту немного более запутанную версию кода выше

def pokeFinder(strng):
    wordList = strng.split()
    pokeList = []
    prevWasWord = False
    for word in wordList:
        if not set('%&').intersection(word) and 'for' not in word:
            clnWord = word.replace(',', '')
            if prevWasWord is True: # 2 poke in a row means same poke
                pokeList[-1] = pokeList[-1] + ' ' + clnWord
            else:
                pokeList.append(clnWord)
                prevWasWord = True
        else:
            prevWasWord = False
    return pokeList

Если нет покемона «из трех слов», и набор правил OP остается постоянным, это всегда должно работать. 2 покерных матча подряд добавляют к предыдущему покемону.

Таким образом, при печати строки '30% for Mr. Mime & 20% for Type: Null' получается ['Mr. Mime', 'Type: Null']

0 голосов
/ 09 января 2020

Используйте позитивный взгляд, это будет работать независимо от капитализации.

(?<=\d\d% for )[A-Za-z]+|(?<=\d% for )[A-Za-z]+

РЕДАКТИРОВАТЬ: Изменено для работы в Python.

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