Search code examples
python-3.xglom

Using the glom library with Python: Turning a list result into a dictionary with key generated by a Python function


I'm using the Python library glom to extract data from a dictionary that contains lists.

This question is about unterstanding how glom works with user defined functions and how I can move data from lists into dictionaries within glom.

As an example, I'm trying to convert the data into a dictionary directly.

# in the real world, this data has way many more fields
data = {'vessels': [{'aisStatic': {'mmsi': 1, 'name': 'name1'}},
               {'aisStatic': {'mmsi': 2, 'name': 'name2'}}],
       'timestamp': None}

# this is the glob spec to extract the data 
spec = ('vessels',[({'mmsi':'aisStatic.mmsi','name':'aisStatic.name'})])

# an example to generate a new key based on data & position
def keyfunc(i, v):
    return f"v{i}-{v['mmsi']}"

result = glom(data, spec)

wanted_result = {keyfunc(i,v): v for i, v in enumerate(result)}

The wanted result looks like this

{'v0-1': {'mmsi': 1, 'name': 'name1'}, 'v1-2': {'mmsi': 2, 'name': 'name2'}}

For the example, I'm using a comprehension outside of glom to get the wanted result, since glom returns a list.

I am looking at a way to get the same results directly via a glom spec.


Solution

  • A working solution is to use Invoke on the enumerate function.

    from glom import merge, Invoke
    
    data = {
        "vessels": [
            {"aisStatic": {"mmsi": 1, "name": "name1"}},
            {"aisStatic": {"mmsi": 2, "name": "name2"}},
        ],
        "timestamp": None,
    }
    
    spec = (
        "vessels",
        [{"mmsi": "aisStatic.mmsi", "name": "aisStatic.name"}],
        Invoke(enumerate).specs(T),
        [lambda x: {f"v{x[0]}-{x[1].get('mmsi')}": x[1]}],
        merge,
    )
    
    print(glom(data, spec))
    

    which returns the requested result

    {'v0-1': {'mmsi': 1, 'name': 'name1'}, 'v1-2': {'mmsi': 2, 'name': 'name2'}}