为什么我的for循环忽略了一个项目?

时间:2016-05-01 07:25:50

标签: python list for-loop dictionary

我是一个完全的初学者,最近学习使用python 我的代码有问题。我试图计算列表addedList的项目数,然后将其添加到字典中的值,如果该值的键存在,如果不存在,我创建一个新的密钥并更新计数。 问题是,在列表中,如果有多个项目,这可能导致一个项目被多次计数。 我的策略是使用remove方法从列表中删除项目。 我相信这会阻止该项目被多次计算。

然而,当我运行代码时。我收到一个错误:IndexEror:index超出范围

def addToInventory(inventory, addedItems):
    lst = list(addedItems)
    for item in range(0, len(addedItems)-1):
        count = lst.count(lst[item])
        if addedItems[item] in inventory:
            inventory[lst[item]] += count
            if count > 1:
                for i in range(0, count):
                    word = lst[item]
                    addedItems.remove(word)
        else:
            inventory.setdefault(lst[item], count)   
inv = {'gold coin': 42, 'rope': 1}
dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby']
inv = addToInventory(inv, dragonLoot)
displayInventory(inv)

我发现在我删除所有项目金币后。我成功地添加了匕首'到字典但没有' ruby​​'。

我希望有人请解释 为什么for循环无法归结为'ruby'? 我该如何解决?

我希望社区了解我在说什么,因为我尽力解决我的问题

谢谢你的帮助。

2 个答案:

答案 0 :(得分:3)

而不是检查计数并使用setdefault,只需遍历战利品清单并尽可能将每个项目添加到相应的条目中,并在必要时创建新条目:

def addToInventory(inventory, addedItems):
    for item in addedItems:
        if item in inventory:
            inventory[item] += 1
        else:
            inventory[item] = 1

还有其他方法可以使用getsetdefaultcollections.defaultdict和/或collections.Counter,但如果你是一个完整的初学者,上述方法可能最容易遵循。

请注意,不需要重新绑定inv = ...,因为该函数会直接改变inv。在不保存参考的情况下调用它:

addToInventory(inv, dragonLoot)

答案 1 :(得分:0)

你的问题在于你的迭代。通常,执行for i in range(...)不是python中的最佳选项,除非您确实需要索引,而不仅仅是项目。

但是,在您的情况下,它实际上会破坏您的代码。循环开始时,for循环从0到倒数第二个(后面会有更多)索引的addedItems 。但是当你从addedItems中删除项目时,它会变短!因此,稍后,您的循环将尝试访问不存在的索引。这就是你用'gold coin'获得indexError的原因。

为什么“红宝石”不起作用?由于range不包含最后一个号码,因此您需要使用range(0,len(addedItems))。因此,使用您的代码,您只能达到倒数第二个值。

最终的结果是,迭代项目是一个更好的主意。要处理可能不存在于字典中的项目,您可以使用get方法,默认值为0:

def addToInventory(inventory, addedItems):
    for item in addedItems:
        inventory[item] = inventory.get(item,0)+1
inv = {'gold coin': 42, 'rope': 1}
dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby']
addToInventory(inv, dragonLoot)
print inv

另请注意,您的函数addToInventory修改了传递给它的(mutable = modifiable)库存,并且不返回任何内容,从而返回None。因此inv = addToInventory(inv, dragonLoot)inv运行时实际修改addToInventory,然后inv设置为None ,该函数的返回值!因此,您只想使用addToInventory(inv, dragonLoot)