2013-08-13 3 views
0

Я пишу простую функцию, чтобы вынуть любые нечетные числа из списка и вернуть список только четных.Как отфильтровать список

def purify(numbers): 
for i in numbers: 
    if i%2!=0: 
     numbers.remove(i) 
return numbers  

print purify([4,5,5,4]) 

при нанесении выше

он возвращает: [4, 5, 4] , почему оленья кожа второй 5 удаляются, поскольку она также justifys КРП?

Im ищет меньше для другого метода проблемы и больше, чтобы понять, почему это происходит.

спасибо и извините, если это глупо д .. Джо

+2

Я знаю, что это дубликат, к сожалению. – squiguy

+0

Код в 'purify' должен быть отступом, иначе он не будет работать. –

+1

, если список длинный, вы можете избавиться от дубликатов с помощью номера = list (set (numbers)) перед сканированием. В этом примере это не стоит, но для больших наборов данных было бы неплохо устранить избыточные проверки перед началом – theodox

ответ

10

При удалении элемента, элементы, которые следуют перемещаются на одну позицию влево. Это приводит к тому, что цикл пропускает некоторые элементы.

Кстати, более идиоматический способ, чтобы написать этот код является

numbers = [num for num in numbers if num % 2 == 0] 
+0

В этом сообщении объясняется метод построения списка, который описывает @NPE. Это называется пониманием списка. http://stackoverflow.com/questions/9061760/how-to-read-aloud-python-list-comprehensions – kelorek

0
>>> listToPurify = [1, 2, 2, 3, 4, 5, 6, 6, 5] 
>>> purified = [i for i in listToPurify if i % 2] 
>>> purified 
[1, 3, 5, 5] 

Кажется, что NPE отправил это раньше меня! Если вы смущены в понимании списков, ознакомьтесь с here.

Если вы предпочитаете использовать цикл for, вам придется иметь дело с тем, что длина списка меняется.

3

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

def purify(numbers): 
    newNumber = [] 
    for i in numbers: 
     if i%2 ==0: 
      newNumber.append(i) 
    return newNumber  

>>>print purify([4,5,5,4]) 
[4, 4] 

Или еще проще:

def purify(numbers): 
    return [i for i in numbers if i % 2 == 0] 

print purify([4,5,5,4]) 
+0

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

1

Вы почти есть. просто добавьте [:] после i для чисел, которые будут проходить через копию списка.

def purify(numbers): 
    for i in numbers[:]: 
     if i%2!=0: 
      numbers.remove(i) 
    return numbers  

print purify([4,5,5,4]) 

Theres хорошее объяснение ниже

python remove duplicates from 2 lists

1

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

Вместо % использовать &. Это немного быстрее.

+0

Будьте осторожны, Python не является ассемблером, а относительная стоимость операций - это не то же самое. 'py -m timeit" [x & 1 == 1 для x в диапазоне (1000)] "' vs 'py -m timeit" [x% 2 == 1 для x в диапазоне (1000)] "' is 143 vs 167 мкс на моем компьютере. Так что почти никакой разницы, но использование% более читаемо, что считается. – user87690

0

Для более четкого изображения распечатайте список на каждой итерации и посмотрите, что происходит в списке, и посмотрите, как продолжается итерация.

# i have taken all odd number to try to remove all numbers from list 
>>> list = [1,3,5,7] 
>>> for num in list: 
...  if num % 2 != 0: 
...   list.remove(num) 
...  print(list) 
... 
[3, 5, 7] 
[3, 7] 

Вы можете видеть, что при каждом удалении элементы перемещались на одну позицию слева.

1

Один из вариантов я не видел упомянутые, по иронии судьбы filter:

>>> filter(lambda x: not x % 2, [4,5,5,4]) 
[4, 4] 
Смежные вопросы