2016-05-01 4 views
0

Я полный новичок и недавно научился использовать python У меня проблема с моим кодом. Я пытаюсь подсчитать количество элементов, если список добавилList, а затем добавить его в значение в словаре, если ключ для этого значения существует, если я не создаю новый ключ и не обновляю счет. Проблема в том, что в списке, где есть более одного элемента, это может привести к тому, что один элемент будет посчитан более одного раза. Моя стратегия заключалась в том, чтобы использовать метод remove для удаления элемента из списка. Я полагал, что это предотвратит подсчет элемента более одного раза.Почему мой цикл for игнорирует элемент?

Однако, когда я запускаю код, он. Я получаю сообщение об ошибке: IndexEror: index out of range

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 не подходит для «рубинов»? Как это исправить?

Я надеюсь, что сообщество понять, что я говорю, как я старался изо всех сил, чтобы сломать мою проблему

спасибо за помощь.

+0

Я получаю еще одну ошибку 'SyntaxError: bad input ('lst')', вы уверены, что это код? – piyushj

+0

Вот золотое правило: не изменяйте то, что вы зацикливаете внутри цикла. –

ответ

0

Ваша проблема с вашей итерацией. Как правило, делать for i in range(...) не самый лучший вариант в python, если вам действительно нужен индекс, а не только элемент.

В вашем случае это фактически нарушает ваш код. Ваш цикл for от 0 до второго, чтобы последний (подробнее об этом позже) индекс добавилItems , когда цикл начался. Но когда вы удаляете элементы из addItems, это становится короче! Таким образом, в какой-то момент ваша петля попытается получить доступ к индексу, которого нет. Вот почему вы получаете 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 изменяет (изменяемый = изменяемый) инвентаризации, который передается в он, и ничего не возвращает, возвращая None. Таким образом, inv = addToInventory(inv, dragonLoot) фактически изменяет inv, когда addToInventory работает, а затем устанавливает inv на None, возвращаемое значение функции! Таким образом, вы захотите использовать только addToInventory(inv, dragonLoot).

+0

Большое спасибо за помощь мне – user6277136

3

Вместо проверки счетчиков и использования 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

Вы должны вернуть 'inventory', иначе ничего не изменится. – Wentao

+0

@Rahn - Он не должен быть ни возвращен, ни отскок. Я добавлю к этому заметку. – TigerhawkT3

+0

Вы правы, тогда вы могли бы просто «addToInventory (inv, dragonLoot)», а не 'inv = addToInventory (inv, dragonLoot)' – Wentao

Смежные вопросы