3

Iterate over nested lists and dictionariesのテーマについて別の質問があります。

上記のリンクのトピックに対する拡張機能が必要です。iterable 要素にはタプルも含まれるようになりました。また、タプルの整数は 16 進文字列に変換する必要があります。そのため、タプルをリストに変換するために、次のコードを試しました。

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: 別のトピックが修正されたため、新しいトピックを作成しました。

4

2 に答える 2

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'}
于 2012-07-16T14:20:10.397 に答える
1

新しいオブジェクトを作成するオーバーヘッドが問題にならない場合は、次の方法を使用することは明らかだと思います。

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)
于 2012-07-16T14:29:35.923 に答える