zoukankan      html  css  js  c++  java
  • Python dictdiffer模块

    Let’s start with an example on how to find the diff between two dictionaries using diff() method:
    
    from dictdiffer import diff, patch, swap, revert
    
    first = {
        "title": "hello",
        "fork_count": 20,
        "stargazers": ["/users/20", "/users/30"],
        "settings": {
            "assignees": [100, 101, 201],
        }
    }
    
    second = {
        "title": "hellooo",
        "fork_count": 20,
        "stargazers": ["/users/20", "/users/30", "/users/40"],
        "settings": {
            "assignees": [100, 101, 202],
        }
    }
    
    result = diff(first, second)
    
    assert list(result) == [
        ('change', ['settings', 'assignees', 2], (201, 202)),
        ('add', 'stargazers', [(2, '/users/40')]),
        ('change', 'title', ('hello', 'hellooo'))]
    Now we can apply the diff result with patch() method:
    
    result = diff(first, second)
    patched = patch(result, first)
    
    assert patched == second
    Also we can swap the diff result with swap() method:
    
    result = diff(first, second)
    swapped = swap(result)
    
    assert list(swapped) == [
        ('change', ['settings', 'assignees', 2], (202, 201)),
        ('remove', 'stargazers', [(2, '/users/40')]),
        ('change', 'title', ('hellooo', 'hello'))]
    Let’s revert the last changes:
    
    result = diff(first, second)
    reverted = revert(result, patched)
    assert reverted == first
    A tolerance can be used to consider closed values as equal. The tolerance parameter only applies for int and float.
    
    Let’s try with a tolerance of 10% with the values 10 and 10.5:
    
    first = {'a': 10.0}
    second = {'a': 10.5}
    
    result = diff(first, second, tolerance=0.1)
    
    assert list(result) == []
    Now with a tolerance of 1%:
    
    result = diff(first, second, tolerance=0.01)
    
    assert list(result) == ('change', 'a', (10.0, 10.5))
    API
    Dictdiffer is a helper module to diff and patch dictionaries.
    
    dictdiffer.diff(first, second, node=None, ignore=None, path_limit=None, expand=False, tolerance=2.220446049250313e-16)
    Compare two dictionary/list/set objects, and returns a diff result.
    
    Return an iterator with differences between two objects. The diff items represent addition/deletion/change and the item value is a deep copy from the corresponding source or destination objects.
    
    >>> from dictdiffer import diff
    >>> result = diff({'a': 'b'}, {'a': 'c'})
    >>> list(result)
    [('change', 'a', ('b', 'c'))]
    The keys can be skipped from difference calculation when they are included in ignore argument of type collections.Container.
    
    >>> list(diff({'a': 1, 'b': 2}, {'a': 3, 'b': 4}, ignore=set(['a'])))
    [('change', 'b', (2, 4))]
    >>> class IgnoreCase(set):
    ...     def __contains__(self, key):
    ...         return set.__contains__(self, str(key).lower())
    >>> list(diff({'a': 1, 'b': 2}, {'A': 3, 'b': 4}, ignore=IgnoreCase('a')))
    [('change', 'b', (2, 4))]
    The difference calculation can be limitted to certain path:
    
    >>> list(diff({}, {'a': {'b': 'c'}}))
    [('add', '', [('a', {'b': 'c'})])]
    >>> from dictdiffer.utils import PathLimit
    >>> list(diff({}, {'a': {'b': 'c'}}, path_limit=PathLimit()))
    [('add', '', [('a', {})]), ('add', 'a', [('b', 'c')])]
    >>> from dictdiffer.utils import PathLimit
    >>> list(diff({}, {'a': {'b': 'c'}}, path_limit=PathLimit([('a',)])))
    [('add', '', [('a', {'b': 'c'})])]
    >>> from dictdiffer.utils import PathLimit
    >>> list(diff({}, {'a': {'b': 'c'}},
    ...           path_limit=PathLimit([('a', 'b')])))
    [('add', '', [('a', {})]), ('add', 'a', [('b', 'c')])]
    The patch can be expanded to small units e.g. when adding multiple values:
    
    >>> list(diff({'fruits': []}, {'fruits': ['apple', 'mango']}))
    [('add', 'fruits', [(0, 'apple'), (1, 'mango')])]
    >>> list(diff({'fruits': []}, {'fruits': ['apple', 'mango']}, expand=True))
    [('add', 'fruits', [(0, 'apple')]), ('add', 'fruits', [(1, 'mango')])]
    Parameters:    
    first – The original dictionary, list or set.
    second – New dictionary, list or set.
    node – Key for comparison that can be used in dot_lookup().
    ignore – List of keys that should not be checked.
    path_limit – List of path limit tuples or dictdiffer.utils.Pathlimit object to limit the diff recursion depth.
    expand – Expand the patches.
    tolerance – Threshold to consider when comparing two float numbers.
    Changed in version 0.3: Added ignore parameter.
    
    Changed in version 0.4: Arguments first and second can now contain a set.
    
    Changed in version 0.5: Added path_limit parameter. Added expand paramter. Added tolerance parameter.
    
    Changed in version 0.7: Diff items are deep copies from its corresponding objects.
    
    dictdiffer.patch(diff_result, destination)
    Patch the diff result to the old dictionary.
    
    dictdiffer.swap(diff_result)
    Swap the diff result.
    
    It uses following mapping:
    
    remove -> add
    add -> remove
    In addition, swap the changed values for change flag.
    
    >>> from dictdiffer import swap
    >>> swapped = swap([('add', 'a.b.c', [('a', 'b'), ('c', 'd')])])
    >>> next(swapped)
    ('remove', 'a.b.c', [('c', 'd'), ('a', 'b')])
    >>> swapped = swap([('change', 'a.b.c', ('a', 'b'))])
    >>> next(swapped)
    ('change', 'a.b.c', ('b', 'a'))
    dictdiffer.revert(diff_result, destination)
    Call swap function to revert patched dictionary object.
    
    Usage example:
    
    >>> from dictdiffer import diff, revert
    >>> first = {'a': 'b'}
    >>> second = {'a': 'c'}
    >>> revert(diff(first, second), second)
    {'a': 'b'}
    dictdiffer.dot_lookup(source, lookup, parent=False)
    Allow you to reach dictionary items with string or list lookup.
    
    Recursively find value by lookup key split by ‘.’.
    
    >>> from dictdiffer.utils import dot_lookup
    >>> dot_lookup({'a': {'b': 'hello'}}, 'a.b')
    'hello'
    If parent argument is True, returns the parent node of matched object.
    
    >>> dot_lookup({'a': {'b': 'hello'}}, 'a.b', parent=True)
    {'b': 'hello'}
    If node is empty value, returns the whole dictionary object.
    
    >>> dot_lookup({'a': {'b': 'hello'}}, '')
    {'a': {'b': 'hello'}}
  • 相关阅读:
    MVC模式的学生信息增删改查
    常用排序算法
    2803 爱丽丝·玛格特罗依德
    3118 高精度练习之除法
    中秋练习题
    poj2011
    P1558 色板游戏
    P1830 轰炸III
    P1656 炸铁路
    1067 机器翻译
  • 原文地址:https://www.cnblogs.com/miaoweiye/p/12607690.html
Copyright © 2011-2022 走看看