1
votes

Comment faire correspondre des données avec une expression régulière

J'ai une liste de tableaux comme:

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

Je veux diviser la liste de tableaux comme

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

J'utilise ce code pour faire le truc mais je ne sais pas ce qui ne va pas:

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']

Le problème est que l'étape de données R10_R84 est divisée en R10 pour l'étape et R84 pour l'enfant Je veux que toutes les données divisé lorsque le préfixe est répété comme R85.


6 commentaires

Devez-vous utiliser regex pour cela? Je trouverais beaucoup plus facile d'écrire du code pour savoir si le préfixe est répété.


Comment l'utiliser s'il vous plaît


Vous dites que vous voulez que les données soient divisées lorsque le préfixe est répété. Par préfixe, voulez-vous dire R8 ? De plus, pour votre dernier élément du tableau, y a-t-il une raison pour laquelle il n'y a qu'un enfant dans votre sortie attendue?


Si par préfixe vous entendez R85 et qu'ils sont regroupés en fonction de l'existence ou non d'autres valeurs comme "STEP", je suis d'accord. Ce n'est pas quelque chose pour lequel vous devriez utiliser regex.


@ Axe319, Oui, je veux dire que R10_R84 sera comme R9 et R8. Pour le dernier élément, R85 est divisé car le préfixe R85 est répété deux fois R85_R84 et R85_R86


@ Axe319, j'ai donc besoin d'utiliser une autre méthode pour faire des choses ou comment vous analysez la solution?


3 Réponses :


1
votes

Je suis sûr que quelqu'un d'autre trouvera une meilleure solution, mais voilà.

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)


1 commentaires

Vous essayez de trier les données avant de faire des choses. Est-il possible de désactiver cela?



1
votes

J'ai légèrement modifié votre solution pour séparer s et c sur _ .

Voici la solution que j'ai trouvée:

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

Ceci est imprimé

  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

Je ne sais pas si c'est exactement ce que vous vouliez mais cela vous montre au moins comment vous pouvez diviser s et c sans avoir à utiliser regex.


1 commentaires

ce n'est pas tout à fait correct car R10_R84 n'a pas de préfixe de répétition sur la ligne ci-dessous, il doit être STEP R10_R84 et CHILD R10_R84. Vérifier ma sortie



1
votes

Vous avez changé votre code pour donner la bonne réponse

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

OutPut:

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)


2 commentaires

Il y a un problème avec l'opérateur, R85_R84 a l'opérateur


print ("Operator", op) print ("MEASURE_CHILD", mc) doit être print ("Operator", last_op) print ("MEASURE_CHILD", last_mc)