Python: return nested dict of values

Question:

I’m typing 3 list of loops, and I need return dict like in docstring. And it’s wrong. How can I solve problem?

For each period you have to count incomes and expenses and total occurrence.

  1. Changes out of functions body are not allowed.
  2. Additional imports are not allowed.
  3. Data could have wholes in periods range ex. 2022-01,2022-03 (missing February), then we assume that item has 0 documents in period

Sample of dict looks like below:

   [
    {
        "package": "FLEXIBLE",
        "created": "2020-03-10T00:00:00",
        "summary": [
            {
                "period": "2019-12",
                "documents": {
                    "incomes": 63,
                    "expenses": 13
                }
            },
            {
                "period": "2020-02",
                "documents": {
                    "incomes": 45,
                    "expenses": 81
                }
            }
        ]
    },
    {
        "package": "ENTERPRISE",
        "created": "2020-03-19T00:00:00",
        "summary": [
            {
                "period": "2020-01",
                "documents": {
                    "incomes": 15,
                    "expenses": 52
                }
            },
            {
                "period": "2020-02",
                "documents": {
                    "incomes": 76,
                    "expenses": 47
                }
            }
        ]
    }
   ]

Code for the task is here:

def task_2(data_in):
    '''
        Return number of documents per period (incomes, expenses, total).
        ex. {
            '2020-04': {
                'incomes': 2480,
                'expenses': 2695,
                'total': 5175
            },
            '2020-05': {
                'incomes': 2673,
                'expenses': 2280,
                'total': 4953
            }
        }
    '''
    period = []
    for term in data_in:
        for dict_val in term['summary']:
            if dict_val['period'] in period:
                continue
            else:
                period.append(dict_val['period'])

    incomes = []
    for term in data_in:
        for dict_val in term['summary']:
            incomes.append(dict_val['documents']['incomes'])

    expenses = []
    for term in data_in:
        for dict_val in term['summary']:
            expenses.append(dict_val['documents']['expenses'])

    # dict_keys = ['incomes', 'expenses', 'total']
    # list1 = [{k: v for k, v in zip(dict_keys, range(len(incomes)))}]

    # return {k: v for k, v in zip(period, list1)}
    return {per: {"incomes": inc, "expenses": exp, "total": inc + exp} for per, inc, exp in
            zip(period, range(len(incomes)), range(len(expenses)))}

I’m typing loops in dict but returns:

{'2019-12': {'incomes': 1, 'expenses': 1, 'total': 2},
 '2020-02': {'incomes': 2, 'expenses': 2, 'total': 4}}
Asked By: Marek Grzesiak

||

Answers:

you need to track the period and save income, expenses, total

data = [
    {
        "package": "FLEXIBLE",
        "created": "2020-03-10T00:00:00",
        "summary": [
            {
                "period": "2019-12",
                "documents": {
                    "incomes": 63,
                    "expenses": 13
                }
            },
            {
                "period": "2020-02",
                "documents": {
                    "incomes": 45,
                    "expenses": 81
                }
            }
        ]
    },
    {
        "package": "ENTERPRISE",
        "created": "2020-03-19T00:00:00",
        "summary": [
            {
                "period": "2020-01",
                "documents": {
                    "incomes": 15,
                    "expenses": 52
                }
            },
            {
                "period": "2020-02",
                "documents": {
                    "incomes": 76,
                    "expenses": 47
                }
            }
        ]}]


records = [record for records in data for record in records['summary']  ]

result =  {}
template = {
        "incomes": 0,
        "expenses": 0,
        "total": 0
    }
for record in records:
    period = record['period']
    if period not in result:
        result[period] = {"incomes": 0,"expenses": 0,"total": 0}
    income = record['documents']['incomes']
    expense = record['documents']['expenses']
    total = income + expense

    result[period]['incomes'] += income
    result[period]['expenses'] += expense
    result[period]['total'] += total


print(result)

# output -> {'2019-12': {'incomes': 63, 'expenses': 13, 'total': 76}, '2020-02': {'incomes': 121, 'expenses': 128, 'total': 249}, '2020-01': {'incomes': 15, 'expenses': 52, 'total': 67}}
Answered By: sahasrara62

You can solve that by creating a dict that has the period as key and a dict with the sums of incomes, expenses and total as value for every key. The structure will be this:

result = dict(
    '2019-12' = dict(
      'incomes' = 0,
      'expenses' = 0,
      'total' = 0,
    ),
    '2020-01' = dict(
      'incomes' = 0,
      'expenses' = 0,
      'total' = 0,
    )
)

But you will instantiate as an empty dict at first, and will populate it as you iterate over the data.

result = dict()
# or simply: result = {}

You will iterate over every term['summary'] in every term, in data_in, as you are already doing with

for term in data_in:
    for dict_val in term['summary']:

Once you have the data to be processed, you need to check if the period of the current dict_val already exists in the result dict. If not, create it with initial values:

if dict_val['period'] not in result:
    result[dict_val['period']] = {'incomes': 0, 'expenses': 0, 'total': 0} 

then, you proceed with doing the calculations for the current dict_val:

result[dict_val['period']]['incomes'] += dict_val['incomes']
result[dict_val['period']]['expenses'] += dict_val['expenses']
result[dict_val['period']]['total'] += dict_val['incomes'] + dict_val['expenses']

Once the iteration is over, you will have your result variable with the data you need

Answered By: notrev
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.