Search code examples
pythondictionaryrecursiondefaultdictglom

Create partial dict from recursively nested field list


After parsing a URL parameter for partial responses, e.g. ?fields=name,id,another(name,id),date, I'm getting back an arbitrarily nested list of strings, representing the individual keys of a nested JSON object:

['name', 'id', ['another', ['name', 'id']], 'date']

The goal is to map that parsed 'graph' of keys onto an original, larger dict and just retrieve a partial copy of it, e.g.:

input_dict = {
  "name": "foobar",
  "id": "1",
  "another": {
    "name": "spam",
    "id": "42",
    "but_wait": "there is more!"
  },
  "even_more": {
    "nesting": {
      "why": "not?"
    }
  },
  "date": 1584567297
}

should simplyfy to:

output_dict = {
  "name": "foobar",
  "id": "1",
  "another": {
    "name": "spam",
    "id": "42"
  },
  "date": 1584567297,
}

Sofar, I've glanced over nested defaultdicts, addict and glom, but the mappings they take as inputs are not compatible with my list (might have missed something, of course), and I end up with garbage.

How can I do this programmatically, and accounting for any nesting that might occur?


Solution

  • you can use:

    def rec(d, f):
    
        result = {}
        for i in f:
            if isinstance(i, list):
                result[i[0]] = rec(d[i[0]], i[1])
            else:
                result[i] = d[i]
    
        return result
    
    f = ['name', 'id', ['another', ['name', 'id']], 'date']
    rec(input_dict, f)
    

    output:

    {'name': 'foobar',
     'id': '1',
     'another': {'name': 'spam', 'id': '42'},
     'date': 1584567297}
    

    here the assumption is that on a nested list the first element is a valid key from the upper level and the second element contains valid keys from a nested dict which is the value for the first element