2016-09-20 179 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']] 

也许有人可以改善它。