2016-09-20 10 views
3

Ich arbeite mit DeepDiff. So habe ich Ergebnisse wie:Parsing DeepDiff Ergebnis

local = [{1: {'age': 50, 'name': 'foo'}}, {2: {'age': 90, 'name': 'bar'}}, {3: {'age': 60, 'name': 'foobar'}}] 
online = [{1: {'age': 50, 'name': 'foo'}}, {2: {'age': 40, 'name': 'bar'}}] 
ddiff = DeepDiff(local, online) 
added, updated = ddiff['iterable_item_added'], ddiff['values_changed'] 
added = {'root[2]': {3: {'age': 60, 'name': 'foobar'}}} 
updated = {"root[1][2]['age']": {'new_value': 90, 'old_value': 40}} 

Nun, ich nehmen wollen:

list_indexes_added = foo(added) 
list_indexes_updated = foo(updated) 

und zu erhalten:

list_indexes_added = [2] 
list_index_updated = [(1,2,'age')] 

auf diese Weise kann ich die Liste manipulieren local und online und in Zukunft die Tabelle online aktualisieren.

Ich denke in Regexs, aber vielleicht gibt es andere Möglichkeiten.

Antwort

2
  • Eine Lösung regex und individuelle Analyse der Spiele sein kann.

  • Ein anderer kann literal_eval nach Regex Parsen auf diesen Strings verwenden, wenn das Ausgabeformat von deepdiff konsistent ist

    from ast import literal_eval 
    import re 
    
    
    def str_diff_parse(str_diff): 
        return [tuple(literal_eval(y) for y in re.findall(r"\[('?\w+'?)\]", x)) for x in str_diff] 
    
    added = {'root[2]': {3: {'age': 60, 'name': 'foobar'}}} 
    updated = {"root[1][2]['age']": {'new_value': 90, 'old_value': 40}} 
    
    list_indexes_added = str_diff_parse(added) 
    list_indexes_updated = str_diff_parse(updated) 
    
    print(list_indexes_added) 
    print(list_indexes_updated) 
    # prints 
    #[(2,)] 
    #[(1, 2, 'age')] 
    

Demo: http://ideone.com/3MhTky

  • auch dictdiffer empfehlen Würde Modul, gibt es das diff als ein konsumables Python-Diff-Objekt, das sein kann zum ursprünglichen Wörterbuch gepatcht, um den aktualisierten zu erhalten oder umgekehrt.
1

Also, ich mit so etwas wie dies gehen würde:

import re 

def foo(diff): 
modded = [] 

for key in diff.keys(): 
    m = re.search('\[(.+)\]', key) 
    modded.append(tuple(m.group(1).split(']['))) 

return modded 

Es wird jeden Schlüssel lesen, extrahieren nur die Indizes (ob numerisch oder String), dann die Zeichenfolge in Scheiben schneiden. Da Ihre gewünschte Ausgabe ein Tupel anzeigt, spuckt sie die Reihenfolge der Indizes als eins zurück und gibt dann die gesamte Liste der Indexmengen zurück (da diff mehrere haben kann).

Dies kann in eine Begreifen einzeilige Liste golfed werden:

import re 

def foo(diff): 
    return [tuple(re.search('\[(.+)\]', key).group(1).split('][')) for key in diff.keys()] 
1

das ist, was ich getan habe:

def getFromSquareBrackets(s): 
    return re.findall(r"\['?([A-Za-z0-9_]+)'?\]", s) 

def auxparse(e): 
    try: 
     e = int(e) 
    except: 
     pass 
    return e 

def castInts(l): 
    return list((map(auxparse, l))) 

def parseRoots(dics): 
    """ 
     Returns pos id for list. 
     Because we have formmatted [{id:{dic}}, {id:{dic}}] 
    """ 
    values = [] 
    for d in dics: 
     values.append(castInts(getFromSquareBrackets(d))) 
    return values 

So:

parseRoots({"root[1][2]['age']": {'new_value': 90, 'old_value': 40}}) 
[[1, 2, 'age']] 

Vielleicht ist es verbessern kann jemand.