Как сопоставить данные с регулярным выражением - PullRequest
1 голос
/ 13 марта 2020

У меня есть список массивов, например:

data = ['- TEST BEGA','R8=11K(10,15A)B','R9=1K(0,3A)B','R10_R84=13MEG(7,14K)R','R85_R84<100K(970,1000K)R',
'R85_R86=10K(9,11K)R']

Я хочу разделить список массивов, как

SCN: TEST BEGA

STEP R8
CHILD R8
Operator =
MEASURE_CHILD 11K(10,15A)B

STEP R9
CHILD R9
Operator =
MEASURE_CHILD 1K(0,3A)B

STEP R10_R84
CHILD R10_R84
Operator =
MEASURE_CHILD 13MEG(7,14K)R

STEP R85
CHILD R84
Operator <
MEASURE_CHILD 100K(970,1000K)R
CHILD R86
Operator =
MEASURE_CHILD 10K(9,11K)R

Я использую этот код, но я не знаю что не так:

def createTreeStandardBloc( self ):
    data = ['- TEST BEGA','R8=11K(10,15A)B','R9=1K(0,3A)B','R10_R84=13MEG(7,14K)R','R85_R84<100K(970,1000K)R','R85_R85=10K(9,11K)R']
    last_s = None
    for i, line in enumerate(data):
        if i == 0:
            print("SCN:", line.strip("- "))
        elif line.strip():
            s, c, op, mc = re.match("^\s*([^_]+)(_\w+)?([<>=])(.*)\s*$", line).groups()
            if s != last_s:
                print("STEP", s)
            print("CHILD", c or s)
            print("Operator",op)
            print("MEASURE_CHILD", mc)
            last_s = s

Проблема в том, что шаг данных R10_R84 делится на R10 для шага и R84 для ребенка. Я хочу, чтобы любые данные были разделены, когда префикс повторяется как R85.

Ответы [ 3 ]

1 голос
/ 13 марта 2020

Я немного изменил ваше решение, чтобы разделить s и c на _.

Вот решение, которое я придумал:

  def createTreeStandardBloc():
    data = ['- TEST BEGA','R8=11K(10,15A)B','R9=1K(0,3A)B','R10_R84=13MEG(7,14K)R','R85_R84<100K(970,1000K)R','R85_R85=10K(9,11K)R', 'R85_R86=10K(9,11K)R']
    last_s = None
    for i, line in enumerate(data):
        if i == 0:
            print("SCN:", line.strip("- "))
        elif line.strip():
            s_c, op, mc = re.match("(.*)([=<>])(.*)", line).groups()
            s_c_list = s_c.split('_')
            s = s_c_list[0]
            if(len(s_c_list) > 1):
                c = s_c_list[1]
            else:
                c = s
            if s != last_s:
                print("STEP", s)
            print("CHILD", c)
            print("Operator",op)
            print("MEASURE_CHILD", mc)
            last_s = s

Это напечатано

SCN: TEST BEGA
STEP R8
CHILD R8
Operator =
MEASURE_CHILD 11K(10,15A)B
STEP R9
CHILD R9
Operator =
MEASURE_CHILD 1K(0,3A)B
STEP R10
CHILD R84
Operator =
MEASURE_CHILD 13MEG(7,14K)R
STEP R85
CHILD R84
Operator <
MEASURE_CHILD 100K(970,1000K)R
CHILD R85
Operator =
MEASURE_CHILD 10K(9,11K)R
CHILD R86
Operator =
MEASURE_CHILD 10K(9,11K)R

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

1 голос
/ 13 марта 2020

Изменили код, чтобы дать правильный ответ

import re

data = ['- TEST BEGA','R8=11K(10,15A)B','R9=1K(0,3A)B','R10_R84=13MEG(7,14K)R'
        ,'R85_R84<100K(970,1000K)R','R85_R85=10K(9,11K)R', 'R92_R86=10K(9,12K)R']
last_s = last_c = last_op = last_mc = None
repeat = 0
for i, line in enumerate(data):
    if i == 0:
        print("SCN:", line.strip("- "))
    elif i == 1:
        last_s, last_c, last_op, last_mc = re.match("^\s*([^_]+)(_\w+)?([<>=])(.*)\s*$", line).groups()
        #last_c = str(last_c)[1:] if last_c != None else last_c           
    elif line.strip():
        s, c, op, mc = re.match("^\s*([^_]+)(_\w+)?([<>=])(.*)\s*$", line).groups()
        #print(s, c, op, mc)
        #print(last_s, last_c, last_op, last_mc)
        if s != last_s:
            if repeat > 0:
                 print("CHILD", last_c or last_s)
                 print("Operator",op)
                 print("MEASURE_CHILD", mc)
            else:
                print("")
                print("STEP", ("" + last_s + last_c if last_c != None else last_s))
                print("CHILD", ("" + last_s + last_c if last_c != None else last_s))
                print("Operator",last_op)
                print("MEASURE_CHILD", last_mc)
            last_s = s
            last_c = c
            last_op = op
            last_mc = mc
            repeat = 0
        else:
            if repeat == 0:
                print("")
                print("STEP", last_s )
            print("CHILD", str(last_c)[1:] if last_c != None else last_c or last_s)
            print("Operator",op)
            print("MEASURE_CHILD", mc)
            last_s = s
            last_c = str(c)[1:] if c != None else c
            last_op = op
            last_mc = mc
            repeat += 1


if repeat == 0:
    print("")
    print("STEP", ("" + last_s + last_c if last_c != None else last_s))
    print("CHILD", ("" + last_s + last_c if last_c != None else last_s))
    print("Operator",last_op)
    print("MEASURE_CHILD", last_mc)
else:
    print("CHILD", str(last_c)[1:] if last_c != None else last_c or last_s)
    print("Operator",op)
    print("MEASURE_CHILD", mc)

OutPut:

SCN: TEST BEGA

STEP R8
CHILD R8
Operator =
MEASURE_CHILD 11K(10,15A)B

STEP R9
CHILD R9
Operator =
MEASURE_CHILD 1K(0,3A)B

STEP R10_R84
CHILD R10_R84
Operator =
MEASURE_CHILD 13MEG(7,14K)R

STEP R85
CHILD R84
Operator =
MEASURE_CHILD 10K(9,11K)R
CHILD R85
Operator =
MEASURE_CHILD 10K(9,12K)R

STEP R92_R86
CHILD R92_R86
Operator =
MEASURE_CHILD 10K(9,12K)R
1 голос
/ 13 марта 2020

Я уверен, что кто-то еще найдет лучшее решение, но здесь идет.

from collections import defaultdict

def get_operator(string):
    '''
    returns the operator found in the string
    '''
    operators = '=><'
    for i in operators:
        if i in string:
            return i

    return None

def createTreeStandardBloc(data):
    # parsed is a default dict of lists which will default
    # to an empty list if a new key is added
    parsed = defaultdict(list)

    # this loop does a few things
    for line in data[1:]:
        # it gets the operator
        oper = get_operator(line)
        # splits the line based on the operator
        split_line = line.split(oper)

        prefixes = split_line[0].split('_')

        # if there aren't 2 prefixes
        # it sets the child to the first and only prefix
        # otherwise it sets it to the second
        if len(prefixes) == 1:
            child = prefixes[0]
        else:
            child = prefixes[1]

        # then it adds it preformatted to the defaultdict
        # this means that any additional items found with
        # the same step prefix will just get added onto that step
        # as a child 
        parsed[prefixes[0]].append('CHILD ' + child)
        parsed[prefixes[0]].append('Operator ' + oper)
        parsed[prefixes[0]].append('MEASURE_CHILD ' + split_line[1])

    # here we start the final formatting of data
    formatted = []
    formatted.append('SCN: ' + data[0].strip('- '))

    for key, items in parsed.items():
        formatted.append(' ')

        # we get the first child prefix here
        child_prefix = items[0][6:]

        # if the child is different from the step 
        # and there are only 3 items
        # we should join them back together
        # I know mutating a collection were iterating over 
        # is sinful but I did it anyway ;)
        if len(items) == 3 and key != child_prefix:
            key = key + '_' + child_prefix
            items[0] = 'CHILD ' + key

        # now we can safely add our step to the formatted list
        formatted.append('STEP ' + key)

        # and the items
        for item in items:
            formatted.append(item)

    return formatted


data = ['- TEST BEGA', 
        'R8=11K(10,15A)B',
        'R9=1K(0,3A)B',
        'R10_R84=13MEG(7,14K)R',
        'R85_R84<100K(970,1000K)R',
        'R85_R86=10K(9,11K)R']

new_data = createTreeStandardBloc(data)

for line in new_data:
    print(line)
...