Лучший способ использовать регулярное выражение

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

import re
import pandas as pd

allAccounts = []
example = '02-0015800-00  NAME1  100 SOME ST  Active  3/8/2021  139.23  139.81  0.42  02-0023901-01  NAME2  101 SOME ST  Active  3/8/2021  512.33  482.96  -5.73'  

rex = '[0-9]{1,2}-[0-9]{1,7}-[0-9]{1,2}'
accounts = re.findall(rex, example)
for account in accounts:       
    example= example.replace(account, f'||{account}')
       
example = [account.replace('  ', '|').split('|') for account in example.split('||')][1:]
allAccounts += example
df = pd.DataFrame(allAccounts)
df

из части регулярного выражения кода я хочу, чтобы он возвращался:

['02-0015800-00  NAME1  100 SOME ST  Active  3/8/2021  139.23  139.81  0.42', ' 02-0023901-01  NAME2  101 SOME ST  Active  3/8/2021  512.33  482.96  -5.73'] 
# or 
'||02-0015800-00  NAME1  100 SOME ST  Active  3/8/2021  139.23  139.81  0.42  ||02-0023901-01  NAME2  101 SOME ST  Active  3/8/2021  512.33  482.96  -5.73'

Код возвращает следующий df, что в конечном итоге я и хочу:

                0       1             2     3          4         5      6      7       8
0   02-0015800-00   NAME1   100 SOME ST Active  3/8/2021    139.23  139.81  0.42    
1   02-0023901-01   NAME2   101 SOME ST Active  3/8/2021    512.33  482.96  -5.73   None

Но я чувствую, что есть лучший способ использовать регулярное выражение, чем то, что я делаю. Читая документы, кажется, что re.sub должен это сделать, но он заменяет только первый номер учетной записи, который встречается, и хочет только заменить номер учетной записи, а не добавлять «||» разделитель в начало.


Обновить:

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

example = '02-0015800-00  NAME1  100 SOME ST  Active  3/8/2021  139.23  139.81  0.42  02-0023901-01  NAME2  101 SOME ST  Active  3/8/2021  512.33  482.96  -5.73'  
rex = re.compile('(?=[0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9])')
re.split(rex, example)

выходы:

['',
 '02-0015800-00  NAME1  100 SOME ST  Active  3/8/2021  139.23  139.81  0.42  ',
 '02-0023901-01  NAME2  101 SOME ST  Active  3/8/2021  512.33  482.96  -5.73']

Вам действительно нужно регулярное выражение, которое соответствует всей информации об учетной записи, или вам просто нужно уметь находить границы? Если второе, то какое фактическое правило говорит вам, где заканчивается информация одной учетной записи и начинается следующая? Просматривая документацию модуля re, вы видели re.split? 90% программирования — это точно понимания проблемы, которую необходимо решить.

Karl Knechtel 10.05.2022 16:58

Я не могу заставить re.split работать. я хочу, чтобы регулярное выражение возвращало ['02-0015800-00 NAME1 100 SOME ST Active 3/8/2021 139.23 139.81 0.42', ' 02-0023901-01 NAME2 101 SOME ST Active 3/8/2021 512.33 482.96 -5.73'] или '||02-0015800-00 NAME1 100 SOME ST Active 3/8/2021 139.23 139.81 0.42 ||02-0023901-01 NAME2 101 SOME ST Active 3/8/2021 512.33 482.96 -5.73'. Где в последнем я могу использовать '||' разделить каждую учетную запись на список.

Infinity Cliff 10.05.2022 17:52

Другой подход: в каждой строке задано количество полей (кажется, их восемь), верно? Что, если вы просто разделите данные на поля (разделенные двойным пробелом), а затем преобразуете эти данные в 8 х N?

Karl Knechtel 10.05.2022 17:54

@Karl Knechtel Хотел бы я, чтобы это было так просто, но их не все 8, у некоторых 7, а у некоторых 9

Infinity Cliff 10.05.2022 17:57

Откуда взялись эти данные? В случаях, когда имеется 9 значений, что они все представляют? В случаях, когда их менее 9, всегда ли отсутствуют одни и те же? Поскольку подобные неоднородные данные — гораздо более серьезная проблема, о которой следовало упомянуть заранее — смысл DataFrame в том, что они представляют собой прямоугольную, непротиворечивую таблицу данных.

Karl Knechtel 10.05.2022 18:03

@Карл Кнехтель, нет, ты слишком много читаешь. Как только я разделю данные на списки, я буду использовать только первые 5 элементов в списке для создания фрейма данных, так что это не является частью вопроса, а просто показывает окончательные конечные результаты. Я спрашиваю только о регулярном выражении кода.

Infinity Cliff 10.05.2022 18:33

@Karl Knechtel Я немного отредактировал вопрос, чтобы, надеюсь, прояснить ситуацию.

Infinity Cliff 10.05.2022 18:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
7
49
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вместо использования разделения вы можете сопоставить значения:

\b\d\d-\d{7}-\d\d\b.*?(?=\s*\b\d\d-\d{7}-\d\d\b.*?|$)

Объяснение

  • \b\d\d-\d{7}-\d\d\b Сопоставьте шаблон с 2 цифрами - 7 цифрами - 2 цифрами, используя квантификатор
  • .*? Подберите любой символ как можно меньше
  • (?=\s*\b\d\d-\d{7}-\d\d\b.*?|$) Положительный просмотр вперед, чтобы подтвердить либо шаблон цифр справа, либо конец строки, чтобы также соответствовать последнему вхождению

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

Пример

import re

pattern = r"\b\d\d-\d{7}-\d\d\b.*?(?=\s*\b\d\d-\d{7}-\d\d\b.*?|$)"

s = "02-0015800-00  NAME1  100 SOME ST  Active  3/8/2021  139.23  139.81  0.42  02-0023901-01  NAME2  101 SOME ST  Active  3/8/2021  512.33  482.96  -5.73"

print(re.findall(pattern, s))

Выход

['02-0015800-00  NAME1  100 SOME ST  Active  3/8/2021  139.23  139.81  0.42', '02-0023901-01  NAME2  101 SOME ST  Active  3/8/2021  512.33  482.96  -5.73']

Если вы должны использовать разделение:

импортировать повторно

pattern = r"\b(?=\d\d-\d{7}-\d\d\b)"

s = "02-0015800-00  NAME1  100 SOME ST  Active  3/8/2021  139.23  139.81  0.42  02-0023901-01  NAME2  101 SOME ST  Active  3/8/2021  512.33  482.96  -5.73"

result = [m.strip() for m in re.split(pattern, s) if m]
print(result)

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

четвертая птица Мне нравится разделенная версия вашего ответа, по крайней мере, для меня легче увидеть, что делает код. Спасибо за объяснение, это очень помогает. Какова цель \b в начале и в конце шаблона? Одна версия быстрее другой?

Infinity Cliff 13.05.2022 14:17

Другие вопросы по теме