2015-03-21 4 views
-1

Я пытался написать часть программы, которая будет удалять любые повторяющиеся элементы в списке, но я получаю list index out of range«Индекс списка вне диапазона» - Python

Вот код:

a_list = [1, 4, 3, 2, 3] 

def repeating(any_list): 
    list_item, comparable = any_list, any_list 
    for x in any_list: 
     list_item[x] 
     comparable[x] 
     if list_item == comparable: 
      any_list.remove(x) 

    print(any_list) 

repeating(a_list) 

Итак, мой вопрос: что случилось?

+0

Что вы думаете 'x' в этом случае? Кроме того, назначение списка другому имени не создает копию, просто добавляет другую ссылку на этот список. –

+0

Ваш тест равенства всегда будет правдой, и, таким образом, элементы будут удалены так, что индексы больше не будут действительны. –

+0

вы даже не знаете, для цикла в python ... сначала возьмите текстовую книгу. – HuStmpHrrr

ответ

1

Ваш код не работает так, как вы думаете.

Сначала вы создаете дополнительные ссылки на тот же список здесь:

list_item, comparable = any_list, any_list 

list_item и comparable просто дополнительные имена для доступа тот же объект списка.

Вы затем цикл по значениям содержали в any_list:

for x in any_list: 

Назначает первый 1, затем 4, затем 3, затем 2, затем 3 снова x.

Далее использовать эти значения в качестве индексов в двух других ссылок на список, но игнорировать результат этих выражений:

list_item[x] 
comparable[x] 

Это ничего, кроме теста не делать, если существуют такие индексы.

Следующая строка тогда всегда истинной:

if list_item == comparable: 

, потому что две переменные ссылаются на тот же объект списка.

Потому что это всегда верно, следующая строка всегда выполняется:

any_list.remove(x) 

Это удаляет первый x из списка, составившего список короче, в то время как еще итерации. Это приводит к тому, что цикл for до пропускает элементов, поскольку он перемещает указатель на следующий элемент. См. Loop "Forgets" to Remove Some Items, почему это так.

В итоге вы получаете 4, затем 3 элемента в списке, поэтому list_item[3] затем сбрасывается и выдает исключение.

правильный способ удаления дубликатов является использование set object:

def repeating(any_list): 
    return list(set(any_list)) 

потому set может содержать только уникальные предметы. Однако это изменит порядок. Если порядок имеет значение, вы можете использовать collections.OrderedDict() object:

def repeating(any_list): 
    return list(OrderedDict.fromkeys(any_list)) 

Подобно set, словарь может содержать только уникальные ключи, но на самом деле OrderedDict также следит за порядком вставки; метод dict.fromkeys() дает каждому элементу в any_list значение None, если элемент уже не был там. Повернувшись, что обратно в список дает уникальные элементы в первый пришел, первый обслужен заказ:

>>> from collections import OrderedDict 
>>> a_list = [1, 4, 3, 2, 3] 
>>> list(set(a_list)) 
[1, 2, 3, 4] 
>>> list(OrderedDict.fromkeys(a_list)) 
[1, 4, 3, 2] 

См How do you remove duplicates from a list in whilst preserving order? больше вариантов по-прежнему.

1

Самый простой способ решить проблему заключается в преобразовании списка в набор, а затем вернуться к списку ...

def repeating(any_list): 
    print list(set(any_list)) 

Вы, вероятно, возникли проблемы, потому что вы изменяете (удаление), итерации по нему.

0

Если вы хотите удалить дубликаты в списке, но не заботиться о элементы форматирования, то вы можете

def removeDuplicate(numlist): 
    return list(set(numlist)) 

Если вы хотите сохранить порядок, то

def removeDuplicate(numlist): 
    return sorted(list(set(numlist)), key=numlist.index)