Python регулярное выражение - PullRequest
       2

Python регулярное выражение

3 голосов
/ 06 декабря 2008

У меня есть такая строка, которую мне нужно проанализировать в 2D массив:

 str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'"

эквивалент массива будет:

arr[0][0] = 813702104
arr[0][1] = 813702106
arr[1][0] = 813702141
arr[1][1] = 813702143
#... etc ...

Я пытаюсь сделать это с помощью REGEX. Приведенная выше строка скрыта на HTML-странице, но я могу быть уверен, что это единственная строка в этом шаблоне на странице. Я не уверен, что это лучший способ, но это все, что у меня есть сейчас.

imgRegex = re.compile(r"(?:'(?P<main>\d+)\[(?P<thumb>\d+)\]',?)+")

Если я запускаю imgRegex.match(str).groups(), я получаю только один результат (первый куплет). Как мне получить несколько совпадений назад или объект двумерного совпадения (если такая вещь существует!)?

Примечание: в отличие от того, как это может выглядеть, это не домашнее задание

Примечание part deux : настоящая строка встраивается в большой файл HTML, поэтому разделение не представляется возможным.

Я все еще получаю ответы на этот вопрос, поэтому я подумал, что лучше отредактировать его, чтобы показать, почему я не меняю принятый ответ. Разделение, хотя и более эффективное для этой тестовой строки, не приведет к извлечению частей из целого HTML-файла. Я мог бы объединить регулярное выражение и разбиение, но это кажется глупым.

Если у вас есть лучший способ найти части из загрузки HTML (шаблон \d+\[\d+\] уникален для этой строки в источнике), я с радостью изменю принятые ответы. Все остальное академично.

Ответы [ 5 ]

5 голосов
/ 06 декабря 2008

Я бы попробовал findall или finditer вместо match.

Редактировать Оли: Да findall работают блестяще, но мне пришлось упростить регулярное выражение:

r"'(?P<main>\d+)\[(?P<thumb>\d+)\]',?"
3 голосов
/ 06 декабря 2008

Я думаю, я не пойду на регулярное выражение для этой задачи. Понимание списка Python достаточно мощное для этого

In [27]: s = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'"

In [28]: d=[[int(each1.strip(']\'')) for each1 in each.split('[')] for each in s.split(',')]

In [29]: d[0][1]
Out[29]: 813702106

In [30]: d[1][0]
Out[30]: 813702141

In [31]: d
Out[31]: [[813702104, 813702106], [813702141, 813702143], [813702172, 813702174]]
1 голос
/ 15 декабря 2008

В качестве альтернативы вы можете использовать синтаксис Python [ для item в list ] для построения списков. Вы должны обнаружить, что это значительно быстрее, чем регулярное выражение, особенно для небольших наборов данных. Большие наборы данных будут показывать менее заметную разницу (он должен загружать механизм регулярных выражений только один раз, независимо от размера), но создатель списков всегда должен быть быстрее.

Начните с разделения строки на запятые:

>>> str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'"
>>> arr = [pair for pair in str.split(",")]
>>> arr
["'813702104[813702106]'", "'813702141[813702143]'", "'813702172[813702174]'"]

Прямо сейчас, это возвращает то же самое, что и просто str.split (","), поэтому не очень полезно, но вы должны быть в состоянии увидеть, как работает listmaker - он перебирает список, присваивая каждое значение item, выполнение оператора и добавление результирующего значения в новый список.

Чтобы добиться чего-то полезного, нам нужно вставить реальный оператор, поэтому мы получаем фрагмент каждой пары, который удаляет одинарные кавычки и заключительную квадратную скобку, а затем разбивает эту удобно расположенную открывающую квадратную скобку:

>>> arr = [pair[1:-2].split("[") for pair in str.split(",")]
>>> arr
>>> [['813702104', '813702106'], ['813702141', '813702143'], ['813702172', '813702174']]

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

>>> arr = [[int(x) for x in pair[1:-2].split("[")] for pair in str.split(",")]
>>> arr
>>> [[813702104, 813702106], [813702141, 813702143], [813702172, 813702174]]

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

1 голос
/ 06 декабря 2008

У меня есть кое-что, что работает с вашим набором данных:

In [19]: str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'"
In [20]: ptr = re.compile( r"'(?P<one>\d+)\[(?P<two>\d+)\]'" )
In [21]: ptr.findall( str )
Out [23]:
[('813702104', '813702106'),
 ('813702141', '813702143'),
 ('813702172', '813702174')]
1 голос
/ 06 декабря 2008

Немного изменив регулярное выражение,

>>> str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]"
>>> imgRegex = re.compile(r"'(?P<main>\d+)\[(?P<thumb>\d+)\]',?")
>>> print imgRegex.findall(str)
[('813702104', '813702106'), ('813702141', '813702143')]

Что представляет собой «2-мерный массив» - в Python «список из 2-х кортежей».

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