解析 DeepDiff 结果

问题描述 投票:0回答:4

我正在与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')]

通过这种方式,我可以操作列表

local
online
,并在将来更新
online
表。

我正在考虑正则表达式,但也许还有其他选择。

python regex algorithm diff
4个回答
5
投票
  • 一种解决方案可以是正则表达式和自定义解析匹配。

  • 如果

    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 对象返回,可以将其修补到原始字典以获取更新的字典,反之亦然。

3
投票

这就是我所做的:

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

也许有人可以改进它。


3
投票

所以,我会选择这样的东西:

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
可能有多个索引集)。

这可以简化为单行列表理解:

import re

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

0
投票

DeepDiff 的作者在这里。 请按照

F.A.Q
中的说明使用 parse_path

>>> from deepdiff import parse_path
>>> parse_path("root[1][2]['age']")
[1, 2, 'age']
>>> parse_path("root[1][2]['age']", include_actions=True)
[{'element': 1, 'action': 'GET'}, {'element': 2, 'action': 'GET'}, {'element': 'age', 'action': 'GET'}]
>>>
>>> parse_path("root['joe'].age")
['joe', 'age']
>>> parse_path("root['joe'].age", include_actions=True)
[{'element': 'joe', 'action': 'GET'}, {'element': 'age', 'action': 'GETATTR'}]
© www.soinside.com 2019 - 2024. All rights reserved.