rlcabral
rlcabral

Reputation: 1546

Loop through multidimensional dictionary and calculate

There must be a question about this, but I can't find.

I have a dictionary like this:

data = {
    "Jan": {
        "2017-01-01 00:00:00": {
            "001": 10,
            "002": 20,
            "003": 30
        },
        "2017-01-01 01:00:00": {
            "001": 20,
            "002": 40,
            "003": 50
        },
        "2017-01-01 02:00:00": {
            "001": 90,
            "002": 50,
            "003": 60
        }
    }
}

I want to loop through the dictionary and calculate the cumulative point, altering the dictionary if possible. For example, for 001 it would be

data["Jan"]["2017-01-01 00:00:00"]["001"] == 10
data["Jan"]["2017-01-01 01:00:00"]["001"] == 30
data["Jan"]["2017-01-01 02:00:00"]["001"] == 120

I don't want to get the final cumulative sum, I want the relative.

Right now I have this code:

import copy
from datetime import datetime, timedelta

copydata = copy.deepcopy(data)
# I made a copy because I have an if statement and Python was
  complaining that the dictionary changed size during iteration

for i, month in enumerate(copydata):
    for dt in copydata[month]:
        for user in copydata[month][dt]:
            current_datetime = datetime.strptime(dt, '%Y-%m-%d %H:00:00')
            cumulativepoints=data[month][dt][user] # getting the current hour's points. Since the loop is in random order, it can start at any time
            if current_datetime.hour > 0: # if the hour is 0 then it's the first hour and I don't need to calculate anything
                for x in range(1, current_datetime.hour+1): # starting at 01:00:00 till the current_datetime.hour plus one to count itself
                    past_time = current_datetime - timedelta(hours=x)
                    past_time = past_time.strftime('%Y-%m-%d %H:00:00')
                    if data[month][past_time]:
                        cumulativepoints += data[month][past_time][user]
                    data[month][past_time][user] = cumulativepoints # <--- the error happens here

But at that line data[month][past_time][user] = cumulativepoints, Python throws an error: TypeError: list indices must be integers, not str

I'm pretty sure this code is a lot more complicated than it should be. But that is the result of many adaptations due to many error messages.

Upvotes: 0

Views: 837

Answers (1)

stovfl
stovfl

Reputation: 15533

Question: Loop through multidimensional dictionary and calculate

You can do it, for instance:

def pp_dict():
    for month in data:
        print('month:{}'.format(month))
        for dt in sorted(data[month]):
            print('\tdt:{}'.format(dt))
            for user in sorted(data[month][dt]):
                print('\t\tuser:{}:{}'.format(user, data[month][dt][user]))

def cum_sum(month, user):
    cum_sum = 0
    for dt in sorted(data[month]):
        cum_sum += data[month][dt][user]
        data[month][dt][user] = cum_sum


for user in ['001']:
    cum_sum('Jan', user)

pp_dict()

Output:

month:Jan
dt:2017-01-01 00:00:00
    user:001:10
    user:002:20
    user:003:30
dt:2017-01-01 01:00:00
    user:001:30
    user:002:40
    user:003:50
dt:2017-01-01 02:00:00
    user:001:120
    user:002:50
    user:003:60

Tested with Python: 3.4.2

Upvotes: 1

Related Questions