2016-09-20 175 views
3

我正在與DeepDiff一起工作。所以我有這樣的結果:解析DeepDiff結果

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}} 

現在,我要帶:

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

,並獲得:

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

,我可以操縱列表localonline並在未來更新online表。

我想在正則表達式中,但也許有其他選擇。

回答

2
  • 一種解決方案可以是匹配的正則表達式和自定義分析。

  • 另一個可以使用literal_eval後這些字符串的正則表達式解析,如果deepdiff輸出格式保持一致

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

演示http://ideone.com/3MhTky

  • 也會推薦dictdiffer模塊,它會返回diff作爲可消耗的python diff對象修補到原始字典以獲取更新的一個,反之亦然。
1

所以,我會像這樣的東西去:

import re 

def foo(diff): 
modded = [] 

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

return modded 

它會讀取每個鍵,只提取指數(無論是數字或字符串),然後切片了繩子。由於你想要的輸出表明一個元組,它會將一系列索引吐回一個,然後返回整個索引集列表(因爲diff可能有多個索引集)。

這可以golfed分解成單行列表解析:

import re 

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

這是我做過什麼:

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 

所以:

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

也許有人可以改善它。