Получение словаря из регулярных выражений - PullRequest
0 голосов
/ 04 марта 2019

У меня есть вопрос, который включает в себя различные шаги.

Я анализирую файл, который выглядит следующим образом:

 9
 123
 0  987
 3  890 234 111
 1 0    1 90    1 34    1 09    1 67    
 1  684321
 2  352 69
 1 1    1 243   1 198   1 678   1 11
 2  098765
 1  143
 1 2    1 23    1 63    1 978   1 379   
 3  784658
 1  43
 1 3    1 546   1 789   1 12    1 098   

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

 0  987
 1  684321
 2  098765
 3  784658

И это строки, значения элементов (игнорируя только первое числопотому что он просто указывает, сколько элементов):

 3  890 234 111
 2  352 69
 1  143
 1  43

В конце это должно выглядеть так:

   d = {987 : [890, 234, 111], 684321 : [352, 69], 
         098765 : [143], 784658 : [43]}

Пока у меня есть это:

findkeys = re.findall(r"\d\t(\d+)\n", line)
findelements = re.findall(r"\d\t(\d+)", line)

listss.append("".join(findelements))
d = {findkeys: listss}

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

И регулярное выражение элементов возвращает мне все строки.

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

Я хочу, чтобы все было просто.Спасибо!

Ответы [ 3 ]

0 голосов
/ 04 марта 2019

Вы можете создать себе синтаксический анализатор, например: parsimonious:

from parsimonious.nodes import NodeVisitor
from parsimonious.grammar import Grammar

data = """
 9
 123
 0  987
 3  890 234 111
 1 0    1 90    1 34    1 09    1 67    
 1  684321
 2  352 69
 1 1    1 243   1 198   1 678   1 11
 2  098765
 1  143
 1 2    1 23    1 63    1 978   1 379   
 3  784658
 1  43
 1 3    1 546   1 789   1 12    1 098   
"""
grammar = Grammar(
    r"""
    data        = (important / garbage)+
    important   = keyline newline valueline
    garbage     = ~".*" newline?
    keyline     = ws number ws number
    valueline   = (ws number)+
    newline     = ~"[\n\r]"
    number      = ~"\d+"
    ws          = ~"[ \t]+"
    """
)

tree = grammar.parse(data)

class DataVisitor(NodeVisitor):
    output = {}
    current = None

    def generic_visit(self, node, visited_children):
        return node.text or visited_children

    def visit_keyline(self, node, children):
        key = node.text.split()[-1]
        self.current = key

    def visit_valueline(self, node, children):
        values = node.text.split()
        self.output[self.current] = [int(x) for x in values[1:]]

dv = DataVisitor()
dv.visit(tree)
print(dv.output)

Это дает

{'987': [890, 234, 111], '684321': [352, 69], '098765': [143], '784658': [43]}

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

0 голосов
/ 04 марта 2019

Как только у вас есть строки в списке (переменная строк), вы можете просто использовать re, чтобы изолировать числа и словарь / понимание списка, чтобы построить желаемую структуру данных.

На основе данных вашего примера, каждый третийстрока - это ключ со значениями в следующей строке.Это означает, что вам нужно только шагнуть в списке на 3.

findall () выдаст вам список чисел (в виде текста) в каждой строке, и вы можете проигнорировать первое с простыми индексами.

import re
value   = re.compile(r"(\d+)")
numbers = [ [int(v) for v in value.findall(line)] for line in lines]
intDict = { key[1]:values[1:] for key,values in zip(numbers[2::3],numbers[3::3]) }

Вы также можете сделать это с помощью split (), но тогда вы должны исключить пустые записи, которые будут создаваться несколькими пробелами в разбиении:

numbers = [ [int(v) for v in line.split() if v != ""] for line in lines]
intDict = { key[1]:values[1:] for key,values in zip(numbers[2::3],numbers[3::3]) }
0 голосов
/ 04 марта 2019
with open('filename.txt') as f:
    lines = f.readlines()   
lines = [x.strip() for x in lines]
lines = lines[2:]
keys = lines[::3]
values = lines[1::3]

выходные строки:

['0  987',
 '3  890 234 111',
 '1 0    1 90    1 34    1 09    1 67',
 '1  684321',
 '2  352 69',
 '1 1    1 243   1 198   1 678   1 11',
 '2  098765',
 '1  143',
 '1 2    1 23    1 63    1 978   1 379',
 '3  784658',
 '1  43',
 '1 3    1 546   1 789   1 12    1 098']

выходные ключи:

['0  987', '1  684321', '2  098765', '3  784658']

выходные значения:

['3  890 234 111', '2  352 69', '1  143', '1  43']

Теперь вам просто нужно собрать их вместе!Итерация по ключам и значениям.

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