we_create
we_create

Reputation: 23

Indexing a value in a nested dictionary

I have a dictionary from an API request that looks somewhat like this:

{
"key 1": "value 1",
"key 2": "value 2",
"key 3": 
    {
        "key 4": "value 4",
        "key 5": "value 5",
        "key 6": "value 6"
    },
... # Additional fields here
}

And I need to save some values to another dictionary like {"key 2": "value 2","key 5":"value 5"}. In an attempt to make the code look nice I want to save the indexes of the values I need to keep in a list like ["key 2", "key 3/key 5"].

However I can't easily index a dictionary with "key 3/key 5" and was wondering if there is a way to do that.

For example:

dict={"username":"user",
      "email":"[email protected]",
      "properties":{
          "favorite color":"blue"
          "favorite food":"apples"
          }
      }
savevalues=["email","properties/favorite food"]

which would return

{"email":"[email protected]","favorite food":"apples"}

Upvotes: 2

Views: 1359

Answers (2)

kungphu
kungphu

Reputation: 4849

Since you're talking about using a list anyway, you could use nested lists/tuples to refer to indices in dictionaries within a dictionary.

d = {
"key 1": "value 1",
"key 2": "value 2",
"key 3": 
    {
        "key 4": "value 4",
        "key 5": "value 5",
        "key 6": "value 6"
    }
}

key_sets = (("key 2",), ("key 3", "key 5"))

for key_set in key_sets:
    value = d
    for key in key_set:
        value = value[key]
    print(value)
# value 2
# value 5


from functools import reduce


# `reduce` using key_sets above, a tuple or list of tuples or lists
print(tuple(
    reduce(
        dict.get, 
        key_set, 
        d
    ) for key_set in key_sets
))
# ('value 2', 'value 5')

keys = ("key 2", "key 3/key 5")

# `reduce` using '/'-separated nested keys, per the example in the question
print(tuple(
    reduce(
        dict.get, 
        key.split("/"), 
        d
    ) for key in keys
))
# ('value 2', 'value 5')

This assumes your key sets are always valid. If that's not an assumption you can make, you'll need to do some exception handling.

Edited to add functional examples.

Upvotes: 1

U13-Forward
U13-Forward

Reputation: 71580

pandas is you new library friend, especially the io.json.nested_to_record function (haha.):

from pandas.io import json  
flat = json.nested_to_record(d)
savevalues=["email","properties/favorite food"]
print({i.split('/')[-1]:flat[i.replace('/','.')] for i in savevalues})

Whole demo:

d={"username":"user",
      "email":"[email protected]",
      "properties":{
          "favorite color":"blue",
          "favorite food":"apples"
          }
      }
from pandas.io import json  
flat = json.nested_to_record(d)
savevalues=["email","properties/favorite food"]
print({i.split('/')[-1]:flat[i.replace('/','.')] for i in savevalues})

Output:

{'email': '[email protected]', 'favorite food': 'apples'}

I recommend this for speed, it's very fast, especially faster than loops :-), pandas is always the fastest in data stuff..., view documentation and be an expert on it...

Upvotes: 0

Related Questions