Distinguish between nested dictionary assignments and list value access in Python dictionaries
I have the dictionary “body” for the body part and its corresponding bounding boxes (xmin, ymin, xmax, ymax):
body = {'lHand': [872, 1075, 920, 1194], 'lfoot': [831, 1665, 928, 1777],
'rfoot': [676, 1624, 741, 1743], 'rKnee': [657, 1313, 726, 1372],
'Lshoul': [809, 678, 885, 740], 'face': [698, 494, 816, 652],
'Lknee': [797, 1323, 862, 1395], 'rShoul': [608, 674, 690, 737],
'rHand': [563, 1074, 620, 1184], 'hips': [641, 977, 848, 1019]}
I want to replace each list value in this dictionary with a nested dictionary where the list element for each key is itself marked: xmin, ymin, xmax, and ymax, respectively. The goal will be this
body['part']['coordinate'] = value
Like
body['face']['xmin'] = 698
For this, I wrote the following:
for (part, bounding_box) in body.items():
for (coordinate, value) in zip(['xmin', 'ymin', 'xmax', 'ymax'], bounding_box):
# the (non-functional) assignment
body[part][coordinate] = value
body[part]['center'] = center(part)
# joints are centers of body parts
joint[part] = body[part]['center']
The error I get,
<pre class=”lang-sh prettyprint-override”>File "body.py", line 110, in <module>
body[part][coordinate] = value
TypeError: list indices must be integers, not str
Makes me feel like Python is reading my attempt to create nested dictionary elements, thinking of it as an attempt to access one of the list members associated with the key “section”.
How do I distinguish between the two operations?
Thanks!
Solution
Yes, the problem with your approach is:
body[part][coordinate] = value
body[part]
returns the list, and then you try to index the list using the string coordinate
, but it fails.
You can just use the dictionary to understand:
>>> labels = ['xmin', 'ymin', 'xmax', 'ymax']
>>> new_body = {k:dict(zip(labels, v)) for k,v in body.items()}
>>> pprint(new_body)
{'Lknee': {'xmax': 862, 'xmin': 797, 'ymax': 1395, 'ymin': 1323},
'Lshoul': {'xmax': 885, 'xmin': 809, 'ymax': 740, 'ymin': 678},
'face': {'xmax': 816, 'xmin': 698, 'ymax': 652, 'ymin': 494},
'hips': {'xmax': 848, 'xmin': 641, 'ymax': 1019, 'ymin': 977},
'lHand': {'xmax': 920, 'xmin': 872, 'ymax': 1194, 'ymin': 1075},
'lfoot': {'xmax': 928, 'xmin': 831, 'ymax': 1777, 'ymin': 1665},
'rHand': {'xmax': 620, 'xmin': 563, 'ymax': 1184, 'ymin': 1074},
'rKnee': {'xmax': 726, 'xmin': 657, 'ymax': 1372, 'ymin': 1313},
'rShoul': {'xmax': 690, 'xmin': 608, 'ymax': 737, 'ymin': 674},
'rfoot': {'xmax': 741, 'xmin': 676, 'ymax': 1743, 'ymin': 1624}}
>>>
As you wish:
>>> new_body['face']['xmin']
698
>>>
Of course, understanding the structure can be replaced by a for loop:
>>> new_body = {}
>>> for k, v in body.items():
... new_body[k] = dict(zip(labels, v))
...
>>> pprint(new_body)
{'Lknee': {'xmax': 862, 'xmin': 797, 'ymax': 1395, 'ymin': 1323},
'Lshoul': {'xmax': 885, 'xmin': 809, 'ymax': 740, 'ymin': 678},
'face': {'xmax': 816, 'xmin': 698, 'ymax': 652, 'ymin': 494},
'hips': {'xmax': 848, 'xmin': 641, 'ymax': 1019, 'ymin': 977},
'lHand': {'xmax': 920, 'xmin': 872, 'ymax': 1194, 'ymin': 1075},
'lfoot': {'xmax': 928, 'xmin': 831, 'ymax': 1777, 'ymin': 1665},
'rHand': {'xmax': 620, 'xmin': 563, 'ymax': 1184, 'ymin': 1074},
'rKnee': {'xmax': 726, 'xmin': 657, 'ymax': 1372, 'ymin': 1313},
'rShoul': {'xmax': 690, 'xmin': 608, 'ymax': 737, 'ymin': 674},
'rfoot': {'xmax': 741, 'xmin': 676, 'ymax': 1743, 'ymin': 1624}}
>>>
I think by reading your code, you’re trying to “take the long term” like this :
>>> new_body = {}
>>> for k, v in body.items():
... new_body[k] = {}
... for coordinate, value in zip(labels, v):
... new_body[k][coordinate] = value
...
>>> pprint(new_body)
{'Lknee': {'xmax': 862, 'xmin': 797, 'ymax': 1395, 'ymin': 1323},
'Lshoul': {'xmax': 885, 'xmin': 809, 'ymax': 740, 'ymin': 678},
'face': {'xmax': 816, 'xmin': 698, 'ymax': 652, 'ymin': 494},
'hips': {'xmax': 848, 'xmin': 641, 'ymax': 1019, 'ymin': 977},
'lHand': {'xmax': 920, 'xmin': 872, 'ymax': 1194, 'ymin': 1075},
'lfoot': {'xmax': 928, 'xmin': 831, 'ymax': 1777, 'ymin': 1665},
'rHand': {'xmax': 620, 'xmin': 563, 'ymax': 1184, 'ymin': 1074},
'rKnee': {'xmax': 726, 'xmin': 657, 'ymax': 1372, 'ymin': 1313},
'rShoul': {'xmax': 690, 'xmin': 608, 'ymax': 737, 'ymin': 674},
'rfoot': {'xmax': 741, 'xmin': 676, 'ymax': 1743, 'ymin': 1624}}
>>>