这是indexloc提供的服务,不要输入任何密码
Skip to content

Improve traverse, calling the callback with the full path key instead of the last one #49

@yurj

Description

@yurj

Sometimes in traverse api it can be useful to have the full path in the callback, for example to find a particular node in the nested dict.

Something like:

def _traverse_collection(d, path, callback):
    if type_util.is_dict(d):
        _traverse_dict(d, path, callback)
    elif type_util.is_list_or_tuple(d):
        _traverse_list(d, path, callback)

def _traverse_dict(d, path, callback):
    keys = list(d.keys())
    for key in keys:
        value = d.get(key, None)
        callback(d, key, path, value)
        path.append(key)
        _traverse_collection(value, path, callback)
        path.pop()


def _traverse_list(ls, path, callback):
    items = list(enumerate(ls))
    for index, value in items:
        callback(ls, index, path, value)
        path.append(index)
        _traverse_collection(value, path, callback)
        path.pop()

def traverse(d, callback):
    if not callable(callback):
        raise ValueError('callback argument must be a callable.')
    _traverse_collection(d, [], callback)

example code:

>>> d = {'dict1': [{'foo': 1, 'bar': 2}], 'dict2': {'baz': 3, 'quux': 4}}
>>> def traverse_item(dct, key, path, value):
...    print('key: {} - path: {} - value: {}'.format(key, path, value))
... 
>>> d.traverse(traverse_item)
key: dict1 - path: [] - value: [{'foo': 1, 'bar': 2}]
key: 0 - path: ['dict1'] - value: {'foo': 1, 'bar': 2}
key: foo - path: ['dict1', 0] - value: 1
key: bar - path: ['dict1', 0] - value: 2
key: dict2 - path: [] - value: {'baz': 3, 'quux': 4}
key: baz - path: ['dict2'] - value: 3
key: quux - path: ['dict2'] - value: 4

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

Status

Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions