Search code examples
pythonpython-3.xdefaultdict

DefaultDict behaves differently in both cases


I have the following :

a = [{ "_id" : { "reportId" : "5a27cda63fff647c33a14b31" }, "amount" : 3000 },
     { "_id" : { "reportId" : "5a27cda63fff647c33a14b31", "name" : "sriram sathyan" }, "amount" : 0 },
     { "_id" : { "reportId" : "5a27cf173f978655f2efbee7" }, "amount" : 1200 },
     { "_id" : { "reportId" : "5a27cf173f978655f2efbee7", "name" : "karthik subbaraj" }, "amount" : 0 }
    ]

I wanted the following structure:

{'reportid1':{'name':'sriram sathyan','amount':3000}, .....}

I tried the followig code:

names = defaultdict(dict)
for item in a:
   report_id = item['_id']['reportId']
   amount = item['amount']
   names[report_id] = {'name': item['_id'].get('name','')}
   if amount != 0:
      names[report_id].update({'amount': amount})
print(dict(names))

Outputs :

{'5a27cda63fff647c33a14b31': {'name': 'sriram sathyan'}, '5a27cf173f978655f2efbee7': {'name': 'karthik subbaraj'}}

( not what i wanted)

I then changed the above code to:

for item in a:
    report_id = item['_id']['reportId']
    amount = item['amount']
    if amount != 0:
        names[report_id] = {'amount': amount}
    names[report_id].update({'name': item['_id'].get('name','')})
print(dict(names))

This outputs:

{'5a27cda63fff647c33a14b31': {'amount': 3000, 'name': 'sriram sathyan'}, '5a27cf173f978655f2efbee7': {'amount': 1200, 'name': 'karthik subbaraj'}}

(What i wanted!!!!!)

So the question is => How could the placement of the if statement cause such a change? Or is it something that i am missing here?


Solution

  • The problem is that in the first case you are overriding names[report_id] on this line:

    names[report_id] = {'name': item['_id'].get('name','')}
    

    Let's follow the 5a27cda63fff647c33a14b31 item in the names dictionary:

    1. On the first iteration of the loop, you are setting the value of names[report_id]:

      {'5a27cda63fff647c33a14b31': {'name': ''}}
      
    2. Then, since the amount is 3000, the dictionary is updated to:

      {'5a27cda63fff647c33a14b31': {'name': '', 'amount': 3000}}
      
    3. Then, on the second iteration of the loop, the dictionary is completely overridden leading to losing the amount value altogether:

      {'5a27cda63fff647c33a14b31': {'name': 'sriram sathyan'}}
      

    Use the debugger to follow the execution line by line, watch how the names dictionary changes.