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

问题描述:

我是一个完整的初学者,最近学习使用python 我的代码有问题。我正在尝试计算列表的数量,如果列表addedList,然后将其添加到字典中的值,如果该值的关键存在,如果没有我创建一个新的密钥并更新计数。 问题在于,如果列表中存在多个项目,则可能会导致一个项目不止一次计数。 我的策略是使用remove方法从列表中删除项目。 我相信这样可以防止物品被计入多次。为什么我的for循环忽略一个项目?

但是,当我运行代码它。我收到一个错误:IndexEror:索引超出范围

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) 

我发现我删除了所有物品后的金币。我成功地将“匕首”添加到字典中,而不是“红宝石”。

我想请某人解释一下
为什么for循环无法调整为'ruby'? 我该如何解决它?

我希望社会明白我在说什么,因为我尽力打破我的问题

谢谢你对我的帮助。

+0

我得到另一个错误'SyntaxError:坏输入('lst')',你确定这是代码? – piyushj

+0

这是一条黄金法则:不要修改循环内循环的东西。 –

你的问题是与你的迭代。一般来说,做一个for i in range(...)不是python的最佳选择,除非你真的需要索引,而不仅仅是项目。

然而,在你的情况下,它确实会破坏你的代码。当循环开始时,for循环从0到倒数第二个(稍后的更多)索引的addedItems 。但是当你从addedItems中移除物品时,它会变短!因此,在稍后的某个时刻,您的循环将尝试访问不存在的索引。这就是为什么你得到'金币'的indexError。

为什么'ruby'没有工作?因为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修改(可变=修改)则传递到库存它,并且不返回任何东西,因此返回None。因此inv = addToInventory(inv, dragonLoot)实际上修改为invaddToInventory运行,然后设置invNone,函数的返回值!所以你只需要使用addToInventory(inv, dragonLoot)

+0

非常感谢你帮助我 – user6277136

而不是检查数量和使用setdefault,只需通过掠夺列表迭代和每个项目的可能时,添加到相应的条目,创建一个新的条目,必要时:

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

还有其他的方法可以做到这与get,setdefault,collections.defaultdict和/或collections.Counter,但如果你是一个完整的初学者,上述方法可能会最容易遵循。

请注意,不需要重新绑定inv = ...,因为函数直接变异inv。说它不保存一个参考:

addToInventory(inv, dragonLoot) 
+0

你必须返回库存,否则没有任何变化。 – Wentao

+0

@Rahn - 它不应该被退回也不会反弹。我会为此添加一个注释。 – TigerhawkT3

+0

你是对的,那么你可以做'addToInventory(inv,dragonLoot)'而不是'inv = addToInventory(inv,dragonLoot)' – Wentao