Вопрос

I have data like so (yes, these tuples are guaranteed to have exactly 5 elements):

ts = ([('a','b','c','d','e'), ('v','w','x','y','z'),
       ('f','g','h','i','j'), ('a','foo','bar',1,2),
       ('f','g','baz',1,3), ('f','g','baz',3,4)])

I'm trying to parse it into a nested dictionary structure like so:

d = {
    'a': {
        'b': {
            'c': [('d','e')]
        },
        'foo': {
            'bar': [(1,2)]
        }
    },
    'f': {
        'g': {
            'h': [('i', 'j')],
            'baz': [(1,3), (3,4)]
        }
    },
    'v': {
        'w': {
            'x': [('y', 'z')]
        }
    }
}

Here's what I have so far; it seems to work properly:

>>> d = {}
>>> for t in ts:
...     if t[0] not in d:
...         d[t[0]] = {t[1]: {t[2]: [(t[3], t[4])]}}
...     elif t[1] not in d[t[0]]:
...         d[t[0]][t[1]] = {t[2]: [(t[3], t[4])]}
...     elif t[2] not in d[t[0]][t[1]]:
...         d[t[0]][t[1]][t[2]] = [(t[3], t[4])]
...     else:
...         d[t[0]][t[1]][t[2]].append((t[3],t[4]))
... 
>>> d
{'a': {'b': {'c': [('d', 'e')]}, 'foo': {'bar': [(1, 2)]}}, 'f': {'g': {'h': [('i', 'j')], 'baz': [(1, 3), (3, 4)]}}, 'v': {'w': {'x': [('y', 'z')]}}}

When I attempted this comprehension, of course, some of the values got overwritten:

>>> {t[0]: {t[1]: {t[2]: [(t[3],t[4])]}} for t in ts}
{'a': {'foo': {'bar': [(1, 2)]}}, 'f': {'g': {'baz': [(3, 4)]}}, 'v': {'w': {'x': [('y', 'z')]}}}

And you really don't want to see the result of this:

>>> {t[0]: {t[1]: {t[2]: [(t[3],t[4])] for t in ts} for t in ts} for t in ts}

How do I correctly write this dict comprehension?

Edit: I'm sorry, I forgot to mention - I need this to be a regular dictionary at the end of the day (it's getting converted to an NSDictionary via PyObjC eventually).

Это было полезно?

Решение

I'd set up the dictionary automatically built its own nested structure as needed:

from collections import defaultdict

dct = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))

Then just append the 2-tuples into the right list:

for a, b, c, d, e in ts:
    dct[a][b][c].append((d, e))

If the different levels of indexing have meanings, I'd use better names than a, b, c though.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top