Listeden bir öğeyi dizine göre kaldırma


1505

Python'daki bir listeden bir öğeyi nasıl kaldırabilirim?

list.removeYöntemi buldum , ancak son öğeyi kaldırmak istediğimi söyleyin, bunu nasıl yaparım? Varsayılan kaldırma listeyi arar gibi görünüyor, ancak herhangi bir arama yapılmasını istemiyorum.


10
@smci: Python listesi diziye dayalıdır: ortadaki bir öğeyi silmek için, sağdaki tüm öğeleri hareket ettirmeniz gerekir, bu nedenle zaman işleminde olması gereken boşluğu kaldırmak için O(n). deque()her iki uçta da verimli işlemler sağlar ancak ortada O (1) yerleştirme / arama / silme sağlamaz.
jfs

@JFSebastian: cPython uygulaması, evet, beni düzelttiğiniz için teşekkürler. Kesinlikle Spec dil listesini nasıl uygulanacağı belirtmez, alternatif uygulamalar bağlantılı listesine kullanmayı seçebilir.
smci

@ smci: Hiçbir pratik Python uygulaması O(n)dizin erişimini kullanmaz a[i](bağlantılı listeler nedeniyle). Not: dizi tabanlı uygulama O(1)dizin erişimi sağlar.
jfs

@JFSebastian: tabii ki. Sadece dil spesifikasyonunun bunu tanımlamadığını , bunun bir uygulama sorunu olduğunu belirttim. (Bunu yapmadığına şaşırdım.)
smci

@ smci bunu geniş çapta hedefliyorsanız, bir şeyi nasıl optimize edebileceğinizi bilmiyorum.
Nick T

Yanıtlar:


1740

delSilmek istediğiniz öğenin dizinini kullanın ve belirtin:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[-1]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8]

Dilimleri de destekler:

>>> del a[2:4]
>>> a
[0, 1, 4, 5, 6, 7, 8, 9]

İşte öğreticinin bölümü.


53
Teşekkürler, pop ve del arasındaki fark nedir?
Joan Venge

37
del aşırı yüklenmiş. Örneğin del a tüm listeyi siler
Brian R. Bondy

34
Başka bir örnek del a [2: 4], 2. ve 3. elemanları siler
Brian R. Bondy

307
pop (), kaldırmak istediğiniz öğeyi döndürür. del sadece siler.

13
Orada "bağlantılı liste" nin bir kanıtı göremiyorum. Bak svn.python.org/projects/python/trunk/Objects/listobject.c nasıl PyList_GetItem()esasen döner ((PyListObject *)op) -> ob_item[i];- iBir dizinin inci elemanı.
glglgl

649

Muhtemelen siz istersiniz pop:

a = ['a', 'b', 'c', 'd']
a.pop(1)

# now a is ['a', 'c', 'd']

Varsayılan olarak, pophiçbir bağımsız değişken olmadan son öğeyi kaldırır:

a = ['a', 'b', 'c', 'd']
a.pop()

# now a is ['a', 'b', 'c']

105
Pop'u (-1) unutmayın. Evet, bu varsayılan, ancak tercih ediyorum, bu yüzden varsayılan olarak hangi son pop'un kullanıldığını hatırlamak zorunda değilim.
S.Lott

282
Katılmıyorum. Eğer "pop" nin programcının etimoloji biliyorsanız (o operasyon kaldırır ve iadeler işte üst , daha sonra 'yığın' veri yapısının) pop()ise tek başına çok açıktır pop(-1)potansiyel tam olarak kafa karıştırıcı çünkü 's gereksiz.
coredumperror

a.pop (-1) sonuncuyu kaldırmak için?
zx1986

14
@ zx1986 a pop, çoğu programlama dilinde Python'da olduğu gibi genellikle son öğeyi kaldırır. Yani -1 belirtin ya da hiçbir şey aynı değildir.
Pascal

30
Bu arada, pop()kaldırdığı öğeyi döndürür.
Bob Stein

136

Diğerleri de belirtildiği gibi pop ve del şunlardır verilen dizinin bir öğeyi kaldırmak için etkili yollar. Ancak sadece tamamlama uğruna (aynı şey Python'da birçok yolla yapılabilir):

Dilimleri kullanma (bu, öğenin orijinal listeden kaldırılmasını sağlamaz):

(Ayrıca bu Python listesiyle çalışırken en az etkili yöntem olacaktır, ancak pop'u desteklemeyen, ancak a tanımlayan kullanıcı tanımlı nesnelerle çalışırken bu yararlı olabilir (ancak verimli değil, tekrar ediyorum) __getitem__):

>>> a = [1, 2, 3, 4, 5, 6]
>>> index = 3 # Only positive index

>>> a = a[:index] + a[index+1 :]
# a is now [1, 2, 3, 5, 6]

Not: Bu yöntemin, popve gibi yerdeki listeyi değiştirmediğini lütfen unutmayın del. Bunun yerine, listelerin iki kopyasını oluşturur (biri başlangıçtan dizine kadar ancak onsuz ( a[:index]) ve dizinden sonra son öğeye ( a[index+1:]) kadar) ve her ikisini de ekleyerek yeni bir liste nesnesi oluşturur. Bu daha sonra list değişkenine ( a) yeniden atanır . Bu nedenle, eski liste nesnesinin kaydı kaldırılır ve dolayısıyla çöp toplanır (orijinal liste nesnesine a dışında bir değişken tarafından başvurulmaması koşuluyla).

Bu, bu yöntemi çok verimsiz hale getirir ve ayrıca istenmeyen yan etkiler de üretebilir (özellikle diğer değişkenler değiştirilmemiş kalan orijinal liste nesnesini gösterdiğinde).

@MarkDickinson'a bunu işaret ettiği için teşekkürler ...

Bu Yığın Taşması yanıtı, dilimleme kavramını açıklar.

Ayrıca, bunun yalnızca pozitif endekslerle çalıştığını da unutmayın.

Nesnelerle birlikte kullanılırken, __getitem__yöntemin tanımlanmış olması ve daha da önemlisi, __add__her iki işlenenden öğeler içeren bir nesne döndürmek için yöntemin tanımlanmış olması gerekir.

Özünde, bu sınıf tanımı aşağıdaki gibi olan herhangi bir nesne ile çalışır:

class foo(object):
    def __init__(self, items):
        self.items = items

    def __getitem__(self, index):
        return foo(self.items[index])

    def __add__(self, right):
        return foo( self.items + right.items )

Bu, listhangi yöntem __getitem__ve __add__yöntemleri tanımlar .

Verimlilik açısından üç yolun karşılaştırılması:

Aşağıdakilerin önceden tanımlandığını varsayın:

a = range(10)
index = 3

del object[index]yöntem:

Şimdiye kadar en verimli yöntem. Bir __del__yöntemi tanımlayan tüm nesneler çalışır .

Sökme aşağıdaki gibidir:

Kod:

def del_method():
    global a
    global index
    del a[index]

demontaj:

 10    0 LOAD_GLOBAL     0 (a)
       3 LOAD_GLOBAL     1 (index)
       6 DELETE_SUBSCR   # This is the line that deletes the item
       7 LOAD_CONST      0 (None)
      10 RETURN_VALUE
None

pop yöntem:

Del yönteminden daha az verimlidir ve silinen öğeyi almanız gerektiğinde kullanılır.

Kod:

def pop_method():
    global a
    global index
    a.pop(index)

demontaj:

 17     0 LOAD_GLOBAL     0 (a)
        3 LOAD_ATTR       1 (pop)
        6 LOAD_GLOBAL     2 (index)
        9 CALL_FUNCTION   1
       12 POP_TOP
       13 LOAD_CONST      0 (None)
       16 RETURN_VALUE

Dilim ve ekleme yöntemi.

En az verimlidir.

Kod:

def slice_method():
    global a
    global index
    a = a[:index] + a[index+1:]

demontaj:

 24     0 LOAD_GLOBAL    0 (a)
        3 LOAD_GLOBAL    1 (index)
        6 SLICE+2
        7 LOAD_GLOBAL    0 (a)
       10 LOAD_GLOBAL    1 (index)
       13 LOAD_CONST     1 (1)
       16 BINARY_ADD
       17 SLICE+1
       18 BINARY_ADD
       19 STORE_GLOBAL   0 (a)
       22 LOAD_CONST     0 (None)
       25 RETURN_VALUE
None

Not: Her üç sökme işleminde de temel olarak son iki satırı görmezden gelin return None. Ayrıca ilk iki satır global değerleri ave index.


4
Dilimleme yönteminiz bir öğeyi listeden kaldırmaz: bunun yerine orijinal listeden ith girdisi dışında tümünü içeren yeni bir liste nesnesi oluşturur . Orijinal liste değiştirilmeden bırakılır.
Mark Dickinson

@MarkDickinson Aynı şeyi netleştirmek için cevabı düzenlediniz ... Lütfen şimdi iyi görünüyorsa bana bildirin?
Raghav RV

6
Belki de cevap tamamen konu ile ilgili değildi, ancak bir öğeyi bir demet gibi değişmez bir nesneden çıkarmanız gerekiyorsa dizin oluşturma yöntemi yararlıdır. pop () ve del () bu durumda çalışmaz.
Caleb

6
@ rvraghav93 tüm yazı boyunca sunulan tüm yöntemlerden a = a[:index] + a[index+1 :], büyük listeler söz konusu olduğunda -trick tasarruf oldu. Diğer tüm yöntemler bir kilitlenmeyle sonuçlandı. Çok teşekkür ederim
user3085931

3
Gerçekten de Mark, huysuzsun. Bu cevap tercih ettiğim cevap çünkü gerçekten pedagojikti. Bu cevaptan ve verilen demontaj detaylarından ve performans üzerindeki etkiden en çok şey öğrendim. Ayrıca dilimleme yöntemi, evet, başka bir nesne oluşturun, ancak şimdi belirtildi ve bazen de ihtiyacınız olan şey bu.
Yohan Obadia

52

popbir öğeyi listeden kaldırmak ve listeden tutmak da yararlıdır. Nerede delöğe gerçekten trashes.

>>> x = [1, 2, 3, 4]

>>> p = x.pop(1)
>>> p
    2

24

2, 3 ve 7 gibi bir listedeki belirli konum öğesini kaldırmak istiyorsanız. kullanamazsın

del my_list[2]
del my_list[3]
del my_list[7]

İkinci öğeyi sildikten sonra, sildiğiniz üçüncü öğe aslında orijinal listedeki dördüncü öğedir. Orijinal listedeki 2., 3. ve 7. öğeleri filtreleyebilir ve aşağıdaki gibi yeni bir liste alabilirsiniz:

new list = [j for i, j in enumerate(my_list) if i not in [2, 3, 7]]

19

Bu ne yapmak istediğinize bağlıdır.

Kaldırdığınız öğeyi döndürmek istiyorsanız şunu kullanın pop():

>>> l = [1, 2, 3, 4, 5]
>>> l.pop(2)
3
>>> l
[1, 2, 4, 5]

Ancak, yalnızca bir öğeyi silmek istiyorsanız, şunu kullanın del:

>>> l = [1, 2, 3, 4, 5]
>>> del l[2]
>>> l
[1, 2, 4, 5]

Ayrıca, deldilimler (örn. del[2:]) Kullanmanızı sağlar .


18

Genellikle aşağıdaki yöntemi kullanıyorum:

>>> myList = [10,20,30,40,50]
>>> rmovIndxNo = 3
>>> del myList[rmovIndxNo]
>>> myList
[10, 20, 30, 50]

15

Yine bir listeden bir elemanı bir dizine göre kaldırmanın başka bir yolu.

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# remove the element at index 3
a[3:4] = []
# a is now [0, 1, 2, 4, 5, 6, 7, 8, 9]

# remove the elements from index 3 to index 6
a[3:7] = []
# a is now [0, 1, 2, 7, 8, 9]

a [x: y], dizinden xile arasındaki öğelere işaret eder y-1. Listenin bu bölümünü boş bir liste ( []) olarak ilan ettiğimizde , bu öğeler kaldırılır.


14

Yalnızca silmek istediğiniz öğeyi arayabilirsiniz. Gerçekten çok basit. Misal:

    letters = ["a", "b", "c", "d", "e"]
    letters.remove(letters[1])
    print(*letters) # Used with a * to make it unpack you don't have to (Python 3.x or newer)

Çıktı: akde


6
Bu çözümü beğendim, ancak elbette listenizde yineleme olmadığı varsayılıyor.
tommy.carstensen

11

Öğeyi listeden kaldırmak için aşağıdaki kodu kullanın:

list = [1, 2, 3, 4]
list.remove(1)
print(list)

output = [2, 3, 4]

Dizin öğesi verilerini listeden kaldırmak istiyorsanız şunu kullanın:

list = [1, 2, 3, 4]
list.remove(list[2])
print(list)
output : [1, 2, 4]

2
Listenizde kopya bulunamayacağı uyarısıyla birlikte gelir.
tommy.carstensen

3
Bu, dizin tarafından değil, eşleşen değerle kaldırılır. Bu, burayı ziyaret eden bazı insanlar için değerli bilgiler olabilir, ancak OP sorusunu hiç yanıtlamaya çalışmaz.
Anthon

8

Daha önce de belirtildiği gibi, en iyi uygulama del (); veya değeri bilmeniz gerekiyorsa pop () işlevini kullanın.

Alternatif bir çözüm, yalnızca istediğiniz öğeleri yeniden yığınlamaktır:

    a = ['a', 'b', 'c', 'd'] 

    def remove_element(list_,index_):
        clipboard = []
        for i in range(len(list_)):
            if i is not index_:
                clipboard.append(list_[i])
        return clipboard

    print(remove_element(a,2))

    >> ['a', 'b', 'd']

eta: hmm ... negatif dizin değerleri üzerinde çalışmaz, düşünür ve günceller

sanırım

if index_<0:index_=len(list_)+index_

... ama aniden bu fikir çok kırılgan gözüküyor. İlginç düşünce deneyi olsa. Görünüşe göre bunu append () / list anlama ile yapmanın 'uygun' bir yolu olmalı.

düşünme


1
Hangi Python sürümü bir işleve sahiptir del()? Bu işlev için listeyi o işleve ilk argüman olarak, ardından dizini mi yoksa önce dizini ve sonra listeyi mi sağlıyorsunuz? Liste bağımsız değişkenini öğe olmadan döndürür mü yoksa silme işlemini yerinde yapar mı? İfadeyi biliyorum del, ama aynı ada sahip bir fonksiyon hakkında değil.
Anthon

8

Bir liste listesiyle çalışıyormuşsunuz gibi gelmiyor, bu yüzden bunu kısa tutacağım. Pop kullanmak istiyorsunuz çünkü listelerdeki öğeleri değil öğeleri silecektir, bunun için del kullanmalısınız. Python'daki son elemanı çağırmak için "-1"

>>> test = ['item1', 'item2']
>>> test.pop(-1)
'item2'
>>> test
['item1']

1
pop()ve delher ikisi de, bir öğenin kendisinin bir liste olup olmamasından bağımsız olarak, sağlanan dizindeki bir öğeyi kaldırır. a = [1, [2, 3], 4]; del a[1]; b = [1, [2, 3], 4]; b.pop(1); assert a == b
Anthon

8

l - değerlerin listesi; inds2rem listesinden dizinleri kaldırmamız gerekir .

l = range(20)
inds2rem = [2,5,1,7]
map(lambda x: l.pop(x), sorted(inds2rem, key = lambda x:-x))

>>> l
[0, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

çalışmıyor, cevap <map at 0x7f4d54109a58>. ve l aralığı (0,20)
Hitesh

7

"Del" işlevini kullanın :

del listName[-N]

Örneğin, son 3 öğeyi kaldırmak istiyorsanız, kodunuz şöyle olmalıdır:

del listName[-3:]

Örneğin, son 8 öğeyi kaldırmak istiyorsanız, kodunuz şöyle olmalıdır:

del listName[-8:]

2
delbir ifadedir . Eğer bir fonksiyon olsaydı, şunu del(listame[-N])
Anthon

7

Bir listeden tek bir öğenin nasıl kaldırılacağı ve farklı yöntemlerin hangi avantajlara sahip olduğu zaten belirtilmiştir. Ancak, birden çok öğeyi kaldırmanın bazı hatalar potansiyeli olduğunu unutmayın:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in indices:
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 7, 9]

Orijinal listenin 3 ve 8 numaralı öğeleri (3 ve 7 değil) kaldırılmıştır (liste döngü sırasında kısaldığı için), bu amaçlanmamış olabilir. Birden çok dizini güvenle kaldırmak istiyorsanız, önce en yüksek dizine sahip öğeleri silmelisiniz, örneğin:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in sorted(indices, reverse=True):
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 8, 9]

4

Veya birden çok dizin kaldırılması gerekiyorsa:

print([v for i,v in enumerate(your_list) if i not in list_of_unwanted_indexes])

Tabii ki de yapabilirdi:

print([v for i,v in enumerate(your_list) if i != unwanted_index])

1
Neden endeksler listesini ters sırada sıralayıp sonra tek tek silmiyorsunuz? Bu şekilde yeni bir liste yapmak zorunda kalmazsınız.
Anthon

3

Dizine göre öğeyi listeden kaldırmak için del veya pop komutunu kullanabilirsiniz. Pop listeden kaldırdığı üyeyi yazdırırken liste o üyeyi yazdırmadan siler.

>>> a=[1,2,3,4,5]
>>> del a[1]
>>> a
[1, 3, 4, 5]
>>> a.pop(1)
 3
>>> a
[1, 4, 5]
>>> 

3

Biri del veya pop kullanabilir, ancak del'i tercih ederim, çünkü indeks ve dilimleri belirtebilirsiniz ve kullanıcıya veriler üzerinde daha fazla kontrol sağlar.

Örneğin, gösterilen listeden başlayarak, son elemanını delbir dilim olarak kaldırabilir ve daha sonra son elemanı kullanarak sonuçtan kaldırabilirsiniz pop.

>>> l = [1,2,3,4,5]
>>> del l[-1:]
>>> l
[1, 2, 3, 4]
>>> l.pop(-1)
4
>>> l
[1, 2, 3]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.