Python: удаление минусов из списка чисел

Вопрос состоит в том, чтобы удалить минусы из чисел.

При выполнении remove_negs([1, 2, 3, -3, 6, -1, -3, 1]) результатом будет: [1, 2, 3, 6, -3, 1]. Результат должен быть [1, 2, 3, 6, 3, 1]. происходит то, что если есть два отрицательных числа в строке (например, -1, -3), то второе число не будет удалено. def main(): numbers = input("Введите список чисел: ") remove_negs(numbers)

def remove_negs(num_list): 
  '''Remove the negative numbers from the list num_list.'''
    for item in num_list: 
        if item < 0: 
           num_list.remove(item) 

    print num_list

main()

person user3161743    schedule 06.01.2014    source источник
comment
Звучит как хорошая работа для понимания списка, которое проверяет val ›= 0.   -  person Dogweather    schedule 07.01.2014
comment
Не удаляйте элементы из списка, который вы повторяете, так как это изменяет индекс элементов, и вы можете в конечном итоге пропустить некоторые элементы.   -  person kylieCatt    schedule 07.01.2014
comment
Как говорили другие, не меняйте содержимое контейнера данных во время его повторения. Перебрать копию - для элемента в списке (num_list):   -  person macfij    schedule 07.01.2014
comment
Кроме того, вам не следует вызывать remove для удаления элемента, если вы уже знаете, где он находится. Это (а) потенциально неправильно, потому что remove удаляет первый элемент, равный item, который может быть не тем, который вам нужен, и (б) медленно, потому что это означает, что вам нужно искать весь список, чтобы найти элемент, даже если вы уже знали, где это было. del num_list[index] всегда лучше. Но как узнать индекс? Просто: for index, item in enumerate(num_list):. (Это всего лишь примечание; это не решит вашу настоящую проблему… но для этого уже есть хорошие ответы и комментарии.)   -  person abarnert    schedule 07.01.2014


Ответы (7)


Обычно не рекомендуется удалять элементы из списка во время его повторения (см. ссылку в моем комментарии для объяснения, почему это так). Лучшим подходом было бы использование понимания списка:

num_list = [item for item in num_list if item >= 0]

Обратите внимание, что строка выше создает новый список и присваивает ему num_list. Вы также можете выполнить "на месте" назначение формы

num_list[:] = ...

который не создает новый список в памяти, а вместо этого изменяет ячейку памяти, на которую уже указывает num_list. Эта разница объясняется более подробно: д">здесь.

person arshajii    schedule 06.01.2014
comment
Я не думаю, что OP на самом деле нужно мутировать num_list здесь, поэтому исходная версия (без назначения слайса), вероятно, была в порядке. Может быть, было бы даже лучше показать оба и объяснить разницу? - person abarnert; 07.01.2014
comment
@abarnert Да, возможно, ты прав. Я отредактирую, чтобы объяснить разницу. - person arshajii; 07.01.2014
comment
@ user3161743: Вы сказали, что результат должен быть [1, 2, 3, 6, 3, 1]. Это именно то, что производит код arshajii. Если бы вы сделали это так, как хотите, результат был бы [1, 2, 3, 3, 6, 1, 3, 1]. - person abarnert; 07.01.2014

Гораздо проще:

>>> a = [ 1, 2, 3, -3, 6, -1, -3, 1]
>>> [x for x in a if x >= 0 ]
[1, 2, 3, 6, 1]

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

def remove_negs(num_list): 
    r = num_list[:]
    for item in num_list: 
        if item < 0: 
           r.remove(item) 
    print r

Это делает то, что вы хотите:

>>> remove_negs([ 1, 2, 3, -3, 6, -1, -3, 1])
[1, 2, 3, 6, 1]

Суть в том, что оператор присваивания r = num_list[:] создает копию num_list. Чтобы не запутать цикл, мы удаляем элементы из r, а не из списка, который мы зацикливаем.

Подробнее: обработка переменных в Python немного тонкая. Python хранит имена переменных, такие как r или num_list, отдельно от данных переменных, таких как [1, 2, 3, 6, 1]. Имена являются просто указателями на данные. Рассмотрим оператор присваивания:

r = num_list

После выполнения этого оператора r и num_list указывают на одни и те же данные. Если вы вносите изменения в данные r, вы также вносите изменения в данные num_list, поскольку они оба указывают на одни и те же данные. Теперь рассмотрим:

r = num_list[:]

Этот оператор говорит python изменить данные num_list, взяв только определенные их элементы. Из-за этого python делает копию данных num_list. Так уж получилось, что [:] указывает, что мы хотим, чтобы все данные num_list не менялись, но это не мешает python делать копии. Копия назначена r. Это означает, что r и mum_list теперь указывают на разные данные. Мы можем вносить изменения в данные r, и это не повлияет на данные num_list, поскольку у них другие данные.

Если это новое для вас, вы можете просмотреть это руководство о подходе Python к именам переменных и переменным данным: Понимание переменных Python и управления памятью

Примеры:

>>> a = [ 1, 2, 3, -3, 6, -1, -3, 1]
>>> b = a   # a and b now point to the same place
>>> b.remove(-1) 
>>> a
[1, 2, 3, -3, 6, -3, 1]

Контраст с:

>>> a = [ 1, 2, 3, -3, 6, -1, -3, 1]
>>> b = a[:] # a and b now point to different data
>>> b
[1, 2, 3, -3, 6, -1, -3, 1]
>>> b.remove(-1)
>>> b
[1, 2, 3, -3, 6, -3, 1]
>>> a
[1, 2, 3, -3, 6, -1, -3, 1]
person John1024    schedule 06.01.2014

Другое решение

filter( lambda x: x>0, [ 1, 2, 3, -3, 6, -1, -3, 1])
[1, 2, 3, 6, 1]
person sergiohzlz    schedule 29.09.2017

Из комментария к ответу arshajii:

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

Удаление отрицательных чисел — это именно то, что явно пытается сделать ваш код, и это также единственный способ получить желаемый результат:

Результат должен быть [1, 2, 3, 6, 3, 1]

Но если вы действительно хотите «убрать отрицательные знаки» с чисел, это еще проще. Например, чтобы удалить отрицательный знак из -3, вы просто отрицаете его и получаете 3, верно? Вы можете сделать это на месте, как в вашем существующем коде:

for index, item in enumerate(num_list): 
    if item < 0: 
       num_list[index] = -item

… или в понимании списка, как у arshajii:

num_list = [-item if item < 0 else item for item in num_list]

И еще проще с функцией abs, которая делает именно это — инвертирует отрицательные числа, оставляя только положительные и нули:

num_list = [abs(item) for item in num_list]

В любом случае, конечно, это даст вам [1, 2, 3, 3, 6, 1, 3, 1], что является неправильным ответом… но если ваш комментарий правильный, это ответ, который вы просили.

person abarnert    schedule 06.01.2014

Другие обычные variable operator non-variable Попробуйте также некоторые условия yoda =)

>>> [i for i in x if 0 <= i]
[1, 2, 3, 6, 1]
person alvas    schedule 06.01.2014

Я думаю, что элегантное решение может быть таким:

import numpy as np

x = [1, 2, 3, -3, 6, -1, -3, 1] # raw data
x = np.array(x) # convert the python list to a numpy array, to enable 
                  matrix operations 
x = x[x >=0] # this section `[x >=0]` produces vector of True and False 
               values, of the same length as the list x
             # as such, this statement `x[x >=0]` produces only the 
               positive values and the zeros

print(x)   
[1 2 3 6 1] # the result
person Amjad    schedule 16.10.2017

снять с чисел отрицательные знаки, это проще всего сделать

def remove_negs(somelist):
    for each in somelist:
        if each < 0:
            somelist[somelist.index(each)] = -each
    print(somelist)

Например

rОтрицательные([-2,5,11,-1])

распечатывает

[2,5,11,1]

person Hiskel Kelemework    schedule 16.11.2016