Search code examples
pythonpython-3.xfunctiondictionarycomparison

Python - dictionaries comparision


I have a problem in python with dictionary comparison. I have 2 dictionaries and I want to compare these and when the key is the same, the value is upgraded to valueFromFirstDictionary + valueFromSecondDictionary.

Function 'addToInventory()' should have 45 coins instead of 3, but where is the problem? In the loop, it prints 45, but when I print all the dictionaries it shows 3.

Here's the problem with function:

def addToInventory(inventory, addedItems):
    dictionaryHelp = {}

    for i in addedItems:                                 
        dictionaryHelp.setdefault(i,0)
        dictionaryHelp[i] = dictionaryHelp[i] + 1

    for i, k in inventory.copy().items():
        for j, l in dictionaryHelp.items():
            #print(i, k, j, l)
            if i == j:
                suma = k + l
                inventory.update({i:suma})
                #inventory[i] = suma
                print(inventory[i])
                break
            else:
                inventory[j] = l

    print(inventory)
    return(inventory)

inv = {'golden coin': 42, 'rope': 1}
dragonLoot = ['golden coin', 'dagger','golden coin', 'golden coin', 'ruby']
inv = addToInventory(inv, dragonLoot)

for k, v in inv.items():
    print(str(k) + ': ' + str(v))
    item_total = item_total + v

The code is also available on Pastebin.


Solution

  • In your for loop, take a close look at the else stuite, where you use j:

    for i, k in inventory.copy().items():
        for j, l in dictionaryHelp.items():
            if i == j:
                # ...
            else:
                inventory[j] = l
    

    You loop over the keys for inventory(), and for each key you loop over dictionaryHelp.items(). And each time i == j is not true, you set inventory[j] = l. It doesn't matter that you set 'golden coin' to 45 at some point, you simply replaced that result.

    However, you don't need to use a double loop. Dictionaries are great at testing if a given key is already there, just use key in dictionary; that's true if you can get a value for that key from that dictionary.

    That means you don't need to loop over both dictionaries, just use the key from one to see if there is a number for the item in the other:

    for item, count in dictionaryHelp.items():
        if item in inventory:
            inventory[item] = inventory[item] + count
        else:
            inventory[item] = count
    
    • There is no need to copy inventory anymore, because you are not looping over it now.
    • Instead of testing for item in inventory, you could use dict.get() to use a default 0 value instead:

      for item, count in dictionaryHelp.items():
          inventory[item] = inventory.get(item, 0) + count
      

      dict.get() is similar to using dict.setdefault(), but without setting the key in the dictionary to the default value.

    • You don't really need to create dictionaryHelp either. Just add the counts directly to your inventory dictionary. I'm using the same dict.get() trick here to start with 0 if an added item wasn't yet there in the inventory:

      def addToInventory(inventory, addedItems):
          for item in addedItems:
              inventory[item] = inventory.get(item, 0) + 1
          return inventory