2015-04-17 5 views
0

rmNegative(L) удаляет отрицательные числа от list L, предполагается, что они содержат только числовые элементы. (Изменяет L, не создает новый список.)Удаление отрицательных чисел из списка Python с использованием цикла while

Как мне это сделать при использовании цикла while? Я попытался кодирования его снова и снова, и все, что я получил, был нескончаемый цикл ..

def rmNegatives(L): 
    pos=len(L)-1 
    while pos>-1: 
     pos=pos 
     if pos<len(L)-1: 
      pos=pos 
      if L[pos]>0: 
       L[:]=L[:] 
       pos=len(L)-2 
      elif L[pos]<0: 
       L[:]=[L[pos]]+L[0:] 
       L[:]=L[1:] 
       pos=len(L)-1 

     elif pos==len(L)-1: 
      pos=pos 
      if L[pos]<0: 
       L[0:]=L[0:pos] 
       pos=len(L)-1 
      elif L[pos]>0: 
       L[:]=L[:] 
       pos=len(L)-2 

rmNegatives([-25,31,-10,23,45,-2]) 

Run the code here

редактировать ** я благодарю вас за ваши ответы. причина, почему мой код не содержит какой-либо формы удаления или индекса, потому что мне было запрещено использовать их (было бы неплохо, если бы они были не ..)

+0

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

+0

Я отредактировал его в ожидании подтверждения курса. –

+0

Похоже, что первый блок - это комментарий? Я пропустил '' '' 'в своем первом редактировании. Может быть, лучше всего показывать только код, который будет работать? –

ответ

-2

Ну, не выделяя новый список сейчас,

>>> list_l = [1, -1, 2, -8] 

>>> length = len(list_l) 
>>> while i < length: 
...  if list_l[i] < 0: 
...    del list_l[i] 
...    length -= 1 
...  else: 
...    i = i + 1 
... 
>>> list_l 
[1, 2] 
+0

Это создает новый список и перезаписывает старую ссылку. Использование цикла, вероятно, является частью урока. – TigerhawkT3

+0

Пожалуйста, любезно скажите мне, что я заблудился, чтобы заслужить проголосовать. – pnv

+0

@pnv: Обычно люди, которые downvote без комментариев никогда не возвращаются и снова смотрят после редактирования. Итак, даже если TigerhawkT3 расстегнул нижний нисходящий (я не знаю, сделал ли он ...), вы, вероятно, не получите других 2 обратно. И я бы не ожидал, что будет слишком много upvotes, потому что ваша новая правильная версия не добавляет ничего, что еще не было в каких-либо других ответах. Поэтому, если вы действительно беспокоитесь о репутации, вы можете просто удалить ответ. – abarnert

-1

Вот моя реализация rmNegative(L).

def rmNegative(L): 
    m = min(L) 
    while m < 0: 
     L.remove(m) 
     m = min(L) 

Это изменяет список и не создает новый список.

1

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

def rmNegative(L): 
    index = len(L) - 1 
    while index >= 0: 
     if L[index] < 0: 
      del L[index] 
     index = index - 1 
+1

Начиная с конца означает, что вам не нужно проверять 'len'. Не использовать 'remove' означает не преподавание вредных привычек (и не обладание квадратичной производительностью). Но ... вы начинаете с 'L [len (L)]' вместо 'L [len (L) -1]', что является 'IndexError'. И это '- 4' вместо' - 1' не может быть хорошей идеей. – abarnert

+0

@abarnert Это то, что я получаю за переименование чего-то, что у меня есть в другом окне. Я не знаю, как я опечатал -4. Это, конечно, не предназначалось. Спасибо, что поймали их. Я отредактировал. –

0

Если вы совершенно не можете позволить себе, чтобы создать новый список, и вы должны использовать while цикл:

l = [1,2,3,-1,-2,-3,4,5] 
x = 0 
while x < len(l): 
    if l[x] < 0: 
    l.remove(l[x]) 
    continue 
    x += 1 

В качестве альтернативы, как это было предложено abarnert (нижняя среда):

l = [1,2,3,-1,-2,-3,4,5] 
x = 0 
while x < len(l): 
    if l[x] < 0: 
    del l[x] 
    continue 
    x += 1 

Если вы абсолютно не можете позволить себе создать новый список, но можете использовать цикл for:

l = [1,2,3,-1,-2,-3,4,5] 
for x in xrange(len(l)): 
    if x < len(l) and l[x] < 0: 
    l.remove(l[x]) 

Если вы можете себе позволить, чтобы создать новый список:

l = [1,2,3,-1,-2,-3,4,5] 
l = [num for num in l if num >= 0] 
+0

Использование 'remove' - плохая идея. Здесь все работает, потому что на самом деле не имеет значения, удалите ли вы «неправильный» '-1', потому что в конечном итоге вы все равно удалите их всех. Но это все еще плохая привычка учиться. Не говоря уже о предоставлении квадратичной производительности вместо линейной без уважительной причины. – abarnert

0

Первый думаю, что вы должны знать, что del L[i] удаляет i-й элемент. (Не используйте L.remove(L[i]);., Что смотрит на i-й элемент, а затем ищет весь список до тех пор, пока не найдет равное значение, а затем удаляет этот)

Но обратите внимание, что при удалении L[3], а затем перейти к L[4] , вы пропустили одно значение - оригинал L[4] теперь L[3], и вам все равно нужно его проверить. Поэтому вы должны не увеличивать i, пока не найдете значение, которое вы держите.

Но если вы просто зацикливаете все индексы, и вы удалили их по пути, вы сбегаете с конца. Таким образом, вам нужно уменьшать длину каждый раз, когда вы удаляете. Или вы также можете просто снова позвонить len(L) и каждый раз проверять новую длину.

Один умный способ решить обе эти проблемы сразу - это отсчет назад, как в Brad Budlong's answer. Но это может облегчить ошибки fencepost.Итак, я сделаю это по-другому.

def rmNegative(L): 
    length = len(L) 
    i = 0 
    while i < length: 
     if L[i] < 0: 
      del L[i] 
      length -= 1 
     else: 
      i += 1 

И все.

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

Начнем с pos=len(L)-1, поэтому мы идем в большой elif. pos=pos ничего не делает. Если это отрицательное число, вы удаляете его и переходите к новому len(L)-1; если это положительное число, вы оставите его и перейдите к len(L)-2. Если это 0, мы не делаем ничего, что означает pos=len(L)-1, и мы просто будем постоянно смотреть на это 0 навсегда.

Итак, это один из способов получить бесконечный цикл. Но давайте предположим, что это не конец 0.

Если мы только что удалили отрицательное число, мы вернемся к elif, и мы знаем, что это нормально, если 0.

Но если мы уже оставили положительное число, то теперь мы имеем pos=len(L)-2, поэтому переходим к if. Опять же, pos=pos ничего не делает. Если это положительное число, мы копируем список сам по себе, который ничего не делает, а затем устанавливает pos=len(L)-2. Это то же самое, что и есть. Итак, если последнее число будет положительным, мы будем продолжать смотреть на этот номер навсегда. Это еще один способ получить бесконечный цикл.

Что делать, если это отрицательно? Затем L[:]=[L[pos]]+L[0:] добавляет значение, которое вы хотите удалить, во весь список (который по-прежнему включает в себя исходную копию значения), L[:]=L[1:] удаляет значение, которое вы только что добавили, поэтому вы получаете те же значения в L, с которых вы начали. Затем вы устанавливаете pos=len(L)-1, который возвращается в конец списка. Мы знаем, что это сработает успешно, и снова вернемся к следующему слоту, который будет по-прежнему иметь одинаковую ценность, поэтому мы будем двигаться вперед и назад навсегда. Итак, этого достаточно, чтобы получить бесконечный цикл.

Что делать, если это было 0? Тогда мы ничего не делаем, поэтому pos и L никогда не меняются, так что это еще один способ получить бесконечный цикл.

Итак, как только мы получим положительный элемент в конце списка, все три возможности для следующего-последнего элемента являются бесконечными циклами.

Откат немного, единственное, что когда-либо набирает ваш код pos, равняется len(L)-1 и len(L)-2. Итак, даже если вы сделали все остальное правильно, как это возможно, возможно, когда-либо закончится в списке с более чем 2 неотрицательными цифрами?

+0

Вычитание 1 из длины решает проблему обхода конца, но у вас есть проблема: если у вас есть два отрицательных числа подряд, вы пропустите второй. Это потому, что вы удаляете элемент i и перемещаетесь на элемент i + 1, но удаление переместило следующий элемент вниз к индексу i, и вы его не проверяете. Вам нужно поставить 'i + = 1' в другое, чтобы исправить это. –

+0

@BradBudlong: Нет, я этого не делаю. Обратите внимание, что 'i + = 1' происходит только в' else'. Также обратите внимание, что есть целый абзац, объясняющий это. – abarnert

+0

Я комментировал вашу оригинальную версию, которая не решила и не объяснила проблему. –

0

Код:

def rmNegatives(L): 
    i = 0 
    while i < len(L): 
     if L[i] < 0: 
      L.pop(i) 
     else: 
      i += 1 
    return L 
Смежные вопросы