3

I have a bit of a complex question that I can't seem to get to the bottom of. I have a list of keys corresponding to a position in a Python dictionary. I would like to be able to dynamically change the value at the position (found by the keys in the list).

For example:

listOfKeys = ['car', 'ford', 'mustang']

I also have a dictionary:

DictOfVehiclePrices = {'car':
                          {'ford':
                              {'mustang': 'expensive',
                               'other': 'cheap'},
                           'toyota':
                              {'big': 'moderate',
                               'small': 'cheap'}
                          },
                       'truck':
                          {'big': 'expensive',
                           'small': 'moderate'}
                      }

Via my list, how could I dynamically change the value of DictOfVehiclePrices['car']['ford']['mustang']?

In my actual problem, I need to follow the list of keys through the dictionary and change the value at the end position. How can this be done dynamically (with loops, etc.)?

Thank you for your help! :)

Tim
  • 11,710
  • 4
  • 42
  • 43
Leopold Joy
  • 4,524
  • 4
  • 28
  • 37

5 Answers5

4

Use reduce and operator.getitem:

>>> from operator import getitem
>>> lis = ['car', 'ford', 'mustang']

Update value:

>>> reduce(getitem, lis[:-1], DictOfVehiclePrices)[lis[-1]] = 'cheap'

Fetch value:

>>> reduce(getitem, lis, DictOfVehiclePrices)
'cheap'

Note that in Python 3 reduce has been moved to functools module.

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1

A very simple approach would be:

DictOfVehiclePrices[listOfKeys[0]][listOfKeys[1]][listOfKeys[2]] = 'new value'
sjs
  • 8,830
  • 3
  • 19
  • 19
1
print reduce(lambda x, y: x[y], listOfKeys, dictOfVehiclePrices)

Output

expensive

In order to change the values,

result = dictOfVehiclePrices
for key in listOfKeys[:-1]:
    result = result[key]

result[listOfKeys[-1]] = "cheap"
print dictOfVehiclePrices

Output

{'car': {'toyota': {'small': 'cheap', 'big': 'moderate'},
 'ford': {'mustang': 'cheap', 'other': 'cheap'}},
 'truck': {'small': 'moderate', 'big': 'expensive'}}
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • This will allow you to retrieve the value, but the questioner wants to be able to modify it. – Tim Nov 12 '13 at 07:43
  • It won't allow to change the value, It's simply a lookup. – Kobi K Nov 12 '13 at 07:45
  • Nice, but you'd probably want to slice the list so you get the first ones and use `setitem` or something on the final value. – Will Nov 12 '13 at 07:46
0

You have a great solution here by @Joel Cornett.

based on Joel method you can use it like this:

def set_value(dict_nested, address_list):
    cur = dict_nested
    for path_item in address_list[:-2]:
        try:
            cur = cur[path_item]
        except KeyError:
            cur = cur[path_item] = {}
    cur[address_list[-2]] = address_list[-1]

DictOfVehiclePrices = {'car':
                      {'ford':
                          {'mustang': 'expensive',
                           'other': 'cheap'},
                       'toyota':
                          {'big': 'moderate',
                           'small': 'cheap'}
                      },
                   'truck':
                      {'big': 'expensive',
                       'small': 'moderate'}
                  }

set_value(DictOfVehiclePrices,['car', 'ford', 'mustang', 'a'])

print DictOfVehiclePrices
  • STDOUT:

{'car': {'toyota': {'small': 'cheap', 'big': 'moderate'}, 'ford': {'mustang': 'a', 'other': 'cheap'}}, 'truck': {'small': 'moderate', 'big': 'expensive'}}

Community
  • 1
  • 1
Kobi K
  • 7,743
  • 6
  • 42
  • 86
-1
def update_dict(parent, data, value):
    '''
    To update the value in the data if the data
    is a nested dictionary
    :param parent: list of parents
    :param data: data dict in which value to be updated
    :param value: Value to be updated in data dict
    :return:
    '''
    if parent:
        if isinstance(data[parent[0]], dict):
            update_dict(parent[1:], data[parent[0]], value)
        else:
            data[parent[0]] = value


parent = ["test", "address", "area", "street", "locality", "country"]
data = {
    "first_name": "ttcLoReSaa",
    "test": {
        "address": {
            "area": {
                "street": {
                    "locality": {
                        "country": "india"
                    }
                }
            }
        }
    }
}
update_dict(parent, data, "IN")

Here is a recursive function to update a nested dict based on a list of keys:

1.Trigger the update dict function with the required params

2.The function will iterate the list of keys, and retrieves the value from the dict.

3.If the retrieved value is dict, it pops the key from the list and also it updates the dict with the value of the key.

4.Sends the updated dict and list of keys to the same function recursively.

5.When the list gets empty, it means that we have reached the desired the key, where we need to apply our replacement. So if the list is empty, the funtion replaces the dict[key] with the value