2014-02-20 6 views
1

Я пытаюсь написать код, чтобы манипулировать список в нечто вроде следующим образом:Как удалить объект по ссылке?

>>> a = [[0,0],[0,1],[0,2]] 
>>> b = a[1] 
>>> b[1] = 3 
>>> a 
[[0,0],[0,3],[0,2]] 
>>> # So far so good 
>>> del b 
>>> a 
[[0,0],[0,3],[0,2]] 
>>> # Huh. 

Как я могу удалить элемент из списка, используя переменную, указывающую на этот элемент?

EDIT:

ОК, так что кажется, эта операция невозможна в Python, который, кажется, стыдно, учитывая, что параллельно вещий способ перебора списка. Эквивалентную операцию в C было бы очень просто сделать с помощью указателей. Закрытие этого вопроса без правильного ответа.

+0

Каков ожидаемый выход? – stonemetal

+0

Ожидаемый выход: [[0,0], [0,2]]. – rophl

+0

@rophl У моего ответа есть надежный способ сделать это, пожалуйста, проверьте. – thefourtheye

ответ

3

Цитируя del docs,

Удаление имени удаляет привязку этого имени с локального или глобального пространства имен, в зависимости от того, происходит ли имя в глобальном заявление в том же блоке кода. Если имя несвязано, будет вызвано исключение NameError .

Итак, вы фактически отменяете имя b из текущего пространства имен, не удаляя данные из списка.

Исключено удаление ссылок на атрибуты, подписки и разрезы на основной объект; удаление разреза в общем случае эквивалентно присвоению пустого фрагмента нужного типа (но даже это определяется срезанным объектом).

Таким образом, вы должны делать

del a[1] 

Это правильный способ сделать удалить элемент.

Edit: Единственный надежный способ сделать это было бы, это

c = [0, 0] 
a = [c, c, [0, 2]] 
b = a[0] 
for idx in xrange(len(a) - 1, -1, -1): 
    if a[idx] is b: 
     del a[idx] 
print a # [[0, 2]] 

Или вы можете сохранить удаление элемента из списка, с .remove, пока не возникает ошибка, как этот

try: 
    while True: 
     a.remove(b) 
except ValueError, e: 
    pass 
print a 
+0

Я понимаю, что это то, что я делаю, поэтому я прошу, как я должен это делать. – rophl

+0

@rophl Проверьте обновленный ответ. – thefourtheye

+0

Что делать, если у меня нет индекса, просто переменная, указывающая на элемент в списке? – rophl

3

Нет, вы не можете этого сделать.

del просто отвязывает имя var от объекта экземпляра. Если вы хотите дель элемент в списке по индексу, используйте pop(index):

In [46]: a=range(4) 

In [47]: a.pop(2) 
Out[47]: 2 

In [48]: a 
Out[48]: [0, 1, 3] 

или del a[index]:

In [50]: del a[2] #this time it deletes "3" in list "a" 

In [51]: a 
Out[51]: [0, 1] 
+0

@falsetru да отредактировал;) – zhangxaochen

+0

Тот же вопрос, который я задал по поводу того, что, если у меня нет индекса, просто переменная, указывающая на элемент в списке? – rophl

+0

@rophl: чем вы не поняли, как pyhton обрабатывает объекты и имена (т. Е. Нет «переменных» и «ссылок», как вы [думаете, вы] их понимаете) – hop

1

Является ли это то, что вы хотите?

>>> a 
[[0, 0], [0, 1], [0, 2]] 
>>> del b[:] 
>>> a 
[[0, 0], [], [0, 2]] 
+0

Это оставляет пустой список в исходном списке :) – thefourtheye

+0

Я предполагаю, что это не то, что он хотел тогда? – user193673

+0

Yup. Сам этот элемент необходимо удалить. – thefourtheye

1

Если вы не знаете индекс, попробуйте следующее. (для проверки идентификации объекта использовался оператор is).

>>> c = [0, 0] 
>>> a = [c, c, [0, 2]] 
>>> b = a[0] 
>>> for j in reversed([i for i, x in enumerate(a) if x is b]): # find indice. 
...  del a[j] 
... 
>>> a 
[[0, 2]] 
+0

Он он, вы теперь избиваете весь смысл 'del': p – thefourtheye

+0

@ thefourtheye, Да, я знаю. Это ответ на комментарий OP: 'Что, если у меня нет индекса, ...' – falsetru

+0

@thefourtheye, обновил ответ, чтобы использовать 'del' (чтобы удалить элемент из списка inplace вместо создания нового списка) – falsetru

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