glom icon indicating copy to clipboard operation
glom copied to clipboard

nested lists

Open uatach opened this issue 7 years ago • 7 comments
trafficstars

I'm dealing with some nested lists and would like to do something like:

>>> target = {
...        'f1': 'v',
...        'f2': [{
...            'f3': 'a',
...            'f4': 0,
...            'f5': [{
...                'f6': 1,
...                'f7': 2, ...
...            }, ...], ...
...        }, ...], ...
...    }
>>> glom(target, ...)
[{'f1': 'v', 'f2.f3': 'a', ..., 'f2.f5.f6': 1},
 {'f1': 'v', 'f2.f4': 0, ..., 'f2.f5.f6': 1},
 {'f1': 'v', 'f2.f3': 'a', ..., 'f2.f5.f7': 2}, ...]

I can get to the list of 'f2.f5.f6' kind of fields but how do I merge this list with parent values? Is this even possible?

uatach avatar May 23 '18 15:05 uatach

I think we have the same issue https://github.com/mahmoud/glom/issues/27 I'm able to access those items but they are returned as nested lists. In your case:

In [21]: spec = {'f2.f3': ("f2", ['f3']), 'f2.f5.f7': ('f2', ['f5'], [['f7']])}

In [22]: glom.glom(target, spec)
Out[22]: {'f2.f3': ['a'], 'f2.f5.f7': [[2]]}

but naturally {'f2.f3': 'a', 'f2.f5.f7': 2} would be better. Thats what I'm struggling with.

wdieter avatar May 23 '18 16:05 wdieter

@wdieter thanks, I've managed something due to the comments on #27. Still, it doesn't seem quite right:

target = {
    'f1': 'v',
    'f2': [{
        'f31': 'a',
        'f41': 0,
        'f51': [{
            'f61': 10,
            'f71': 20,
        },],
    },{
        'f32': 'a',
        'f42': 1,
        'f52': [{
            'f62': 11,
            'f72': 21,
        },],
    },
    ],
}

glom({'data': target}, ('data', lambda d: [{'f1': d['f1'], 'f2': v} for v in d['f2']]))
#[{'f1': 'v', 'f2': {'f31': 'a', 'f41': 0, 'f51': [{'f61': 10, 'f71': 20}]}},
# {'f1': 'v', 'f2': {'f32': 'a', 'f42': 1, 'f52': [{'f62': 11, 'f72': 21}]}}]

It looks like I'll have to keep unpacking things at each step... @mahmoud @kurtbrose is there a better way?

uatach avatar May 24 '18 01:05 uatach

I have this exact question as well.

liquidgenius avatar Nov 02 '18 01:11 liquidgenius

I would hope to have a string spec as follows to access nested lists:

target = {
    'f1': 'v',
    'f2': [{
        'f51': [{
            'f61': 10,
            'f71': 20,
        },],
    },...
...
}

glom(target, "f2[0].f51[0].f61")
# 10

Here you can quickly see when you're drilling into a dict key or list index. One tool that does spelunks nested containers in a similar way is Munch, a py 3 variant of a Bunch. Can we emulate that access style in parallel with the spec?

pylang avatar Oct 19 '19 23:10 pylang

@pylang that's interesting. I think it's a little different than OP's ask. Regarding that syntax, I'll note that dict keys are also accessed with square brackets, so I'm not sure that you're accessing a list is universally obvious, not to mention that glom also traverses attribute accesses with the same . syntax in the string.

You can get list indexes in your example with glom(target, "f2.0.f51.0.f61")

For more explicit access, I'd say take a look at the T object.

mahmoud avatar Oct 20 '19 01:10 mahmoud

For the rest of folks looking for upward merging, we're working on some features that'll help!

mahmoud avatar Oct 20 '19 01:10 mahmoud

glom(target, "f2.0.f51.0.f61") does the job. Thanks.

pylang avatar Oct 21 '19 23:10 pylang