2

I have the data in this format -

[
    {'gstin_code': 'A', 
     'price_effective': 1199.0, 
     'company_id': 489, 
     'month': datetime.datetime(2018, 6, 1, 0, 0), 
     'year': datetime.datetime(2018, 1, 1, 0, 0)
     },
    {'gstin_code': 'B', 
     'price_effective': 1199.0, 
     'company_id': 489, 
     'month': datetime.datetime(2018, 6, 1, 0, 0), 
     'year': datetime.datetime(2018, 1, 1, 0, 0)
     },
    {'gstin_code': 'C', 
     'price_effective': 1199.0, 
     'company_id': 489, 
     'month': datetime.datetime(2018, 6, 1, 0, 0), 
     'year': datetime.datetime(2018, 1, 1, 0, 0)
     }
]

The output expected is this -

{
    "2": {
        "2018": {
            "3": {
                "27AA": 1799
            },
            "4": {
                "03AA": 1299,
                "04AA": 1499,
                "05AA": 699,
                "06AA": 599,
                "07AA": 199,
                "09AA": 499,
                "19AA": 599,
                "23AA": 770,
                "27AA": 420,
                "27AA": 499
            },
            "5": {
                "03AA": 1399,
                "27AA": 399,
                "27AA": 640
            }
         }
     }
  }

i.e {company_id:{year:{month:{gst:price_effective}}}}

Those values also come as None, like company_id, year, month, gst do come as None.

The solution which works is this -

for f_bag in data:
    if f_bag['company_id'] in result and f_bag['company_id'] is not None:
        if f_bag['year'].year in result[f_bag['company_id']] and f_bag['year'].year is not None:
            if f_bag['month'].month in result[f_bag['company_id']][f_bag['year'].year] and f_bag['month'].month is not None:
                if f_bag['gstin_code'] in result[f_bag['company_id']][f_bag['year'].year][f_bag['month'].month] and f_bag['gstin_code'] is not None:
                    pass
                else:
                    result[f_bag['company_id']][f_bag['year'].year][f_bag['month'].month][f_bag['gstin_code']] = f_bag['price_effective']
            else:
                result[f_bag['company_id']][f_bag['year'].year][f_bag['month'].month] = {}
        else:
            result[f_bag['company_id']][f_bag['year'].year] = {}
    else:
        result[f_bag['company_id']] = {}

Any elegant way to avoid these if else statements?

Alexander
  • 87,529
  • 23
  • 162
  • 169
Arjunsingh
  • 517
  • 6
  • 14
  • @Lucas how is this question related to pretty print? It seems to be about filtering out keys with `None` values. – woozyking Sep 21 '18 at 05:48
  • Its just to print an existing dictionary, In my case its an array of dict – Arjunsingh Sep 21 '18 at 05:48
  • @Lucas This is not about pretty printing a nested dict, but about setting default empty dicts in a nested dict. – blhsing Sep 21 '18 at 05:48
  • I haven't asked about printing either, do read the question carefully. Moreover I have provided the answer which gives the output, so its pretty easy to understand what the question is – Arjunsingh Sep 21 '18 at 05:50
  • Sorry, my mistake. I did it in a hurry because I thought it was a duplicate – Lucas Sep 21 '18 at 05:50
  • 1
    Possible duplicate of [What is the best way to implement nested dictionaries?](https://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries) – blhsing Sep 21 '18 at 05:52
  • 1
    A few techniques you can apply. First, in the context of a for loop, you can resort to early `continue` to cover the smallest block of flow in your `if..else` flow controls -- this is good to save you from overly nested flow controls. Second, you can try to apply logical `or` for default values, such that `None or ` can be used to apply the same effect of simple `if..else` – woozyking Sep 21 '18 at 05:54
  • 1
    Addition to my second point earlier, you can leverage `dict.get()` method here to make for some nice "Pythonic" way to achieve what you want too – woozyking Sep 21 '18 at 05:56

1 Answers1

1

with collections.defaultdict you can remove the checks whether the key exist in the dictionary:

from collections import defaultdict
def nested_dict():
    return defaultdict(nested_dict)

def toNested(data):
    nd = nested_dict()
    for aa in data:    
        nd[aa['company_id']][aa['year'].year][aa['month'].month][aa['gstin_code']] = aa['price_effective']
    return nd

import pprint
pp = pprint.PrettyPrinter(indent=4)
pp.pprint( toNested(data) )

see Create Nested Dictionaries in python for more details and benchmarks

napuzba
  • 5,255
  • 3
  • 17
  • 30