2 Вопрос: Как можно извлечь подстроки, используя ключевые слова и индекс?

вопрос создан в Wed, May 8, 2019 12:00 AM

Я пытаюсь получить определенную подстроку после ключевого слова из строки данных. Эти собранные подстроки затем объединяются.

Есть ли более простой подход, чем несколько итераций for-loop, без использования регулярных выражений?

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

Используя эти индексы, я могу сказать, что подстрока ключевого слова A находится между индексом ключевого слова A и ключевым словом B. Поэтому я присоединяю эти строки из списка.

Такой подход кажется слишком сложным.

data_string = "safpifucr keywordA: ejeca pfiktecr 3697406324 keywordB: 2505098781 epef ahemahkuj  keywordC: ezivwut 2564556750 inanrune"
keywords = ['keywordA:', 'keywordB:', 'keywordC:']
split_string = data_string.split()
keyword_index = []
# Getting the indexes of keywords
for index, word in enumerate(split_string, start=0):
    if word in keywords:
        keyword_index.append((word, index))


def getSubString(split_string, key_index, next_key_index):
    subString = []
    for index, sub in enumerate(split_string, start=0):
        if index > key_index and index < next_key_index:
            subString.append(sub)
    return subString
# Get SubString after Keyword A
subA = getSubString(split_string, keyword_index[0][1], keyword_index[1][1])
print(' '.join(subA)) # ejeca pfiktecr 3697406324

# Get SubString after Keyword A
subB = getSubString(split_string, keyword_index[1][1], keyword_index[2][1])
print(' '.join(subB)) # 2505098781 epef ahemahkuj

# Get SubString after Keyword A
subC = getSubString(split_string, keyword_index[2][1], len(split_string))
print(' '.join(subC)) # ezivwut 2564556750 inanrune

Мне было интересно, существует ли более простой способ достижения вышеуказанного результата без необходимости многократно повторять строку split_string. (П * ключевые слова)

Update

Это требуется для просмотра банковских записей, в которых вся информация о транзакции находится в одной непрерывной строке. Вся важная информация находится за ключевыми словами, за которыми следует двоеточие. По разным причинам я не буду делиться точной строкой, но я перестроил некоторые образцы, которые идентичны по структуре только с вымышленным содержанием.

# Approach 2 of blhsing with RANDOM-DATA
keywords = set(['Empfänger:', 'Verwendungszweck:', 'Zahlungsempfänger:', 'Auftraggeberinformation:', 'Zahlungsreferenz:'])
mapping = {}
keyword = None
data_list = (
    'ONLINE BANKING VOM 1.10 UM 20:18  Empfänger:  Henrietta Mullins  Verwendungszweck:  bestellung 57E639 2019-06-10 terriblesuccess.SG',
    'SEPA Lastschrift  Zahlungsempfänger:  planetwötrap-AG  Verwendungszweck:  planetwötrap-AG-AG 460/487835-389 Ina Gill  Auftraggeberinformation:  3740930917-909/387187-3',
    'SEPA Lastschrift  Zahlungsempfänger:  AMAZON PAYMENTS EUROPE S.C.A.  Verwendungszweck:  409-7235170-354760 AMZN Mktp FI 3882385979  Auftraggeberinformation:  6V0RRQCT6GAACLH8',
    'POS 50,0648 FK K2 5.22 11:17 these cutting 5359')
for data_string in data_list:
    for word in data_string.split():
        if word in keywords:
            keyword = word
            print('if word in keywords: ', word)
        elif keyword in mapping:
            mapping[keyword] += ' ' + word
            print('elif keyword in mapping: ', word)
        elif keyword:
            mapping[keyword] = word
            print('elif keyword: ', word)
print(mapping)

Это выводит

{'Empfänger:': 'Henrietta Mullins', 'Verwendungszweck:': 'bestellung 57E639 2019-06-10 terriblesuccess.SG SEPA Lastschrift planetwötrap-AG-AG 460/487835-389 Ina Gill 409-7235170-354760 AMZN Mktp FI 3882385979', 'Zahlungsempfänger:': 'planetwötrap-AG AMAZON PAYMENTS EUROPE S.C.A.', 'Auftraggeberinformation:': '3740930917-909/387187-3 SEPA Lastschrift 6V0RRQCT6GAACLH8 POS 50,0648 FK K2 5.22 11:17 these cutting 5359'} р>     

1
  1. Что не так с использованием регулярных выражений? Это лучший подход для данной проблемы.
    2019-05-08 16: 41: 33Z
  2. Как бы вы использовали список ключевых слов с регулярными выражениями?
    2019-05-08 16: 50: 28Z
2 ответа                              2                         

Вы можете использовать re.findall с шаблоном чередования, построенным на основе объединения списка ключевых слов, чтобы создать изречение, которое сопоставляет ключевые слова с их значениями:

import re
dict(re.findall(r'\b({0})\s+(.*?)\s*\b(?={0}|$)'.format('|'.join(map(re.escape, keywords))), data_string))

Это возвращает:

{'keywordA:': 'ejeca pfiktecr 3697406324',
 'keywordB:': '2505098781 epef ahemahkuj',
 'keywordC:': 'ezivwut 2564556750 inanrune'}

С этим условием становится просто выводить значение каждого заданного ключевого слова.

    
1
2019-05-08 18: 11: 39Z
  1. Да, это проще с точки зрения «занимает всего одну строку». Лично мне не нравится это из-за моей неопытности в RE, а также потому, что это очень нечитаемо. Тем не менее, это жизнеспособный подход, который я должен рассмотреть, я рассмотрю его позже.
    2019-05-08 17: 37: 24Z
  2. Это также более эффективно, потому что строка сканируется только один раз. Кроме того, это нечитаемо, только если вы не знаете RE, с которым я настоятельно рекомендую вам ознакомиться.
    2019-05-08 17: 38: 47Z
  3. Увидев, насколько короткой стала реализация, я могу только согласиться.
    2019-05-08 17: 45: 34Z
  4. Я не понимаю часть re.escape, потому что re.escape - это функция, и здесь отсутствуют паратезы и параметры. Итак, не могли бы вы уточнить это для меня?
    2019-05-09 09: 04: 27Z
  5. Неважно! Это внутри функции карты! Хорошо, я думаю, я понял это сейчас.
    2019-05-09 09: 11: 00Z

Другой подход, который также сканирует строку только один раз, состоит в том, чтобы перебирать слова в строке данных, сохранять ключевое слово, если ключевое слово найдено (сначала преобразовать keywords в набор для более эффективных поисков), или если слово не ключевое слово, назначить и объединить слово со значением dict для сопоставления dict под текущим ключевым словом:

keywords = set(keywords)
mapping = {}
keyword = None
for word in data_string.split():
    if word in keywords:
        keyword = word
    elif keyword in mapping:
        mapping[keyword] += ' ' + word
    elif keyword:
        mapping[keyword] = word

mapping становится:

{'keywordA:': 'ejeca pfiktecr 3697406324',
 'keywordB:': '2505098781 epef ahemahkuj',
 'keywordC:': 'ezivwut 2564556750 inanrune'}
    
2
2019-05-08 19: 14: 16Z
  1. Я предпочитаю такой подход.
    2019-05-08 18: 03: 04Z
  2. Оказывается, этот конкретный подход не работает для моих конкретных data_strings. Ваш пример регулярного выражения делает однако. Что означает, что я был вынужден изучить это, и действительно, это начинает становиться немного более читаемым.
    2019-05-09 09: 03: 22Z
  3. Я вижу. Можете ли вы обновить свой вопрос с образцом фактического data_strings, который не работает с этим решением? Это должно быть легко исправимо, когда будут идентифицированы сведения о вашем фактическом data_strings.
    2019-05-09 17: 08: 02Z
  4. Я обновил вопрос, но должен отметить, что я определенно переключился на ваш ответ по регулярному выражению, поскольку он делает его более понятным (если RE известен, все еще работает на что ^^) и эффективно. Проблема с этим ответом состоит в том, что он не прекращает добавление в отображение, даже если это уже следующий элемент в списке. (что проблематично, потому что они вообще не должны путаться)
    2019-05-10 07: 02: 28Z
источник размещен Вот