【问题标题】:Iterate over nested lists, tuples and dictionaries迭代嵌套列表、元组和字典
【发布时间】:2012-07-15 08:37:38
【问题描述】:

我对@9​​87654321@ 的主题还有另一个问题。

我需要上面链接主题的一些扩展功能。可迭代元素现在还包含 元组。元组中的整数也需要转换为十六进制字符串。因此,我尝试使用以下代码将元组转换为列表。

for path, value in objwalk(element):
    if isinstance(value, tuple):
        parent = element
        for step in path[:-1]:
            parent = parent[step]
        parent[path[-1]] = list(value)

但我的问题是,元组中的元组没有被转换。如何以优雅的方式将“子元组”转换为列表?

最好的问候 哇

PS:我创建了一个新主题,因为另一个主题对我来说是固定的。

【问题讨论】:

标签: python loops


【解决方案1】:

在这种情况下,直接在objwalk 结构遍历器中处理元组会更容易。这是一个修改后的版本,它在遍历元组以查找嵌套元素之前将其转换为列表:

def objwalk(obj, path=(), memo=None):
    if memo is None:
        memo = set()
    iterator = None
    if isinstance(obj, dict):
        iterator = iteritems
    elif isinstance(obj, (list, set)) and not isinstance(obj, string_types):
        iterator = enumerate
    if iterator:
        if id(obj) not in memo:
            memo.add(id(obj))
            for path_component, value in iterator(obj):
                if isinstance(value, tuple):
                    obj[path_component] = value = list(value)
                for result in objwalk(value, path + (path_component,), memo):
                    yield result
            memo.remove(id(obj))
    else:
        yield path, obj

使用您上一个问题中稍作修改的示例,以及我在该问题中给您的相同 hex 解决方案:

>>> element = {'Request': (16, 2), 'Params': ('Typetext', [16, 2], 2), 'Service': 'Servicetext', 'Responses': ({'State': 'Positive', 'PDU': [80, 2, 0]}, {})}
>>> for path, value in objwalk(element):
...     if isinstance(value, int):
...         parent = element
...         for step in path[:-1]:
...             parent = parent[step]
...         parent[path[-1]] = hex(value)
... 
>>> element
{'Params': ['Typetext', ['0x10', '0x2'], '0x2'], 'Request': ['0x10', '0x2'], 'Responses': [{'State': 'Positive', 'PDU': ['0x50', '0x2', '0x0']}, {}], 'Service': 'Servicetext'}

【讨论】:

    【解决方案2】:

    如果创建新对象的开销不是问题,我认为很清楚:

    def transform(obj):
        _type = type(obj)
        if _type == tuple: _type = list
        rslt = _type()
        if isinstance(obj, dict):
            for k, v in obj.iteritems():
                rslt[k] = transform(v)
        elif isinstance(obj, (list, tuple)):
            for x in obj:
                rslt.append(transform(x))
        elif isinstance(obj, set):
            for x in obj:
                rslt.add(transform(x))
        elif isinstance(obj, (int, long)):
            rslt = hex(obj)
        else:
            rslt = obj
    
        return rslt
    
    element = transform(element)
    

    【讨论】:

    • 看起来是解决这个问题的一种简单而好的方法。但它不适用于嵌套元组。 PS:第一个“elif”行中有一个“)”。
    • @wewa 很高兴你有这个想法。恕我直言,这不是首选解决方案,但我只是在展示这个想法。我已经编辑了代码以显示使用嵌套元组是多么容易。
    • 效果很好,对初学者来说也不难。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-22
    • 1970-01-01
    • 2015-09-19
    • 2015-10-03
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    相关资源
    最近更新 更多