3

I'm new to programming. I'm trying to figure out how to subtract 'budgeted' from 'actual' and then update the value to 'variance' using a nested for loop. However, I've read that it isn't the best practice to change a dictionary while iterating. So far, I've been stumped on how to proceed.

for i in properties:
    for j in properties[i]:
        if j == "actual":
            sum = properties[i][j]
            print('\nActual:' , sum)
        if j == "budgeted":
            sum_two = properties[i][j]
            print('Budgeted:' , sum_two)
            diff = sum_two - sum
            print('Variance:', diff)    
default_value = 0

properties = {587: {'prop_name': 'Collington'}, 'rental_income': {'apartment_rent': '5120-0000', 'resident_assistance': '5121-0000', 'gain_loss': '5120-0000'}, 51200000: {'actual': 29620, 'budgeted': 30509, 'variance': default_value}, 51210000: {'actual': 25620, 'budgeted': 40509, 'variance': default_value}, ............
Red
  • 26,798
  • 7
  • 36
  • 58
Barry L.
  • 33
  • 4
  • You can update values in the dictionary as you are iterating over it. What you shouldn't do is delete or insert new values. – Sri May 27 '20 at 00:48

5 Answers5

2

just iterate through the dictionary and check if in the inner dictionary, if actual, variance and budgeted exists or not, if yes then modify the variance value

for k, v in properties.items():
    if (('actual' in v.keys()) and ('variance' in v.keys()) and ('budgeted' in v.keys())):
            properties[k]['variance'] = properties[k]['actual']-properties[k]['budgeted']
sahasrara62
  • 10,069
  • 3
  • 29
  • 44
1

There is nothing wrong with modifying the values inside a dictionary while iterating. The only thing that is not recommend is modifying the dictionary itself, that is adding/removing elements.

orlp
  • 112,504
  • 36
  • 218
  • 315
1

Try something like:

for i in properties:
    properties[i]['variance'] = properties[i]['budgeted'] - properties[i]['actual']

If you aren't sure that bugeted and actual exist in the dictionaries, you should catch the KeyError and handle approprately:

for i in properties:
    try:
        properties[i]['variance'] = properties[i]['budgeted'] - properties[i]['actual']
    except KeyError:
        properties[i]['variance'] = -1 # Set to some special value or just pass
Dallan
  • 504
  • 4
  • 13
  • couldn't you use `dict.get()` instead of the try block? – bherbruck May 27 '20 at 01:02
  • Some would argue that it is more pythonic to try first and then ask for forgiveness later: https://stackoverflow.com/a/12265860/5075269 – Dallan May 27 '20 at 01:04
  • but using try and except will increase to much time if suppose there is not `variance` present or not plus it is also creating a new key `variance` where variance is not even required so using `if x in dic.keys()` is better choice – sahasrara62 May 27 '20 at 01:41
1

Your data is in a strange format, I always try to group like objects together in dictionaries rather than have metadata and "lists" of items in the same level of a dictionary. This will work for you though:

for prop in properties:
    p = properties[prop]
    if 'actual' or 'budgeted' in p.keys():
        # get() wont error if not found, also default to 0 if not found
        p['variance'] = p.get('budgeted', 0) - p.get('actual', 0)

import json
print(json.dumps(properties, indent=4))

Output:

{
    "587": {
        "prop_name": "Collington"
    },
    "rental_income": {
        "apartment_rent": "5120-0000",
        "resident_assistance": "5121-0000",
        "gain_loss": "5120-0000"
    },
    "51200000": {
        "actual": 29620,
        "budgeted": 30509,
        "variance": 889
    },
    "51210000": {
        "actual": 25620,
        "budgeted": 40509,
        "variance": 14889
    }
}
bherbruck
  • 2,167
  • 1
  • 6
  • 17
0
sum = None
sum_two = None
for i in properties:
        for j in i:
            if j=="actual":
                sum = properties [i]["actual"] 
                print('\nActual:' , sum)
            if j == "budgeted":
                sum_two = properties[i]["budgeted"]
                print('Budgeted:' , sum_two)
                diff = sum_two - sum
                print('Variance:', diff)

I didn't get what mean exactly, but this should work.

Ahmad Ali
  • 704
  • 1
  • 10
  • 28