Adarsh
Adarsh

Reputation: 3583

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?

Upvotes: 1

Views: 33

Answers (2)

alecxe
alecxe

Reputation: 474271

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.

Upvotes: 1

Jean-François Fabre
Jean-François Fabre

Reputation: 140307

the problem is that you have identical keys, one with amount equal to zero in the data, and one with amount not zero.

in the first loop, the entry with a non-zero amount is created first, then is overwritten by the entry with zero amount

So both codes overwrite some entries, but the first code overwrites the entries you want to keep, whereas the second one (the one that works) overwrite the entries with zero amount.

Upvotes: 2

Related Questions