2012-10-01 9 views
10

Jak usunąć element z listy, jeśli pasuje do podłańcucha?Usuwanie pozycji z listy pasującej do podłańcucha - Python

Próbowałem usuwanie elementu z listy za pomocą metody pop() i enumerate ale wydaje się, że brakuje mi kilku sąsiadujących ze sobą elementów, które muszą być usunięte:

sents = ['@$\tthis sentences needs to be removed', 'this doesnt', 
    '@$\tthis sentences also needs to be removed', 
    '@$\tthis sentences must be removed', 'this shouldnt', 
    '# this needs to be removed', 'this isnt', 
    '# this must', 'this musnt'] 

for i, j in enumerate(sents): 
    if j[0:3] == "@$\t": 
    sents.pop(i) 
    continue 
    if j[0] == "#": 
    sents.pop(i) 

for i in sents: 
    print i 

wyjściowa:

this doesnt 
@$ this sentences must be removed 
this shouldnt 
this isnt 
#this should 
this musnt 

Pożądany wyjściowa:

this doesnt 
this shouldnt 
this isnt 
this musnt 
+3

Klasyczny przypadek usuwania elementów z listy podczas iteracji nad tą listą. Przeczytaj dziesiątki innych pytań związanych z przepełnieniem stosu, które odnoszą się do tego. Zobacz także [note in the docs] (http://docs.python.org/reference/compound_stmts.html#for). –

+1

należy zawsze unikać zmiany długości kontenera podczas iteracji przez niego, jest to przepis na katastrofę. – wim

+0

Generalnie zwykle lepiej jest stworzyć nową przefiltrowaną listę niż próbować modyfikować listę w miejscu. Niezmienne algorytmy są zawsze łatwiejsze do zrozumienia (chociaż nie zawsze łatwiej jest wymyślić, jak pisać). Kiedy po prostu wymieniasz wartości, czasami zwiększa się wydajność pracy w miejscu, ale kiedy usuwasz lub wstawiasz na środku listy, zazwyczaj uzyskujesz efektywność i mniej logiczną logikę. – abarnert

Odpowiedz

20

Jak abo ut coś prostego jak:

>>> [x for x in sents if not x.startswith('@$\t') and not x.startswith('#')] 
['this doesnt', 'this shouldnt', 'this isnt', 'this musnt'] 
+0

ah ze zrozumieniem listy, elegancki! pozwól mi spróbować. – alvas

+0

+1 za najczystszą odpowiedź. – abarnert

8

To powinno działać:

[i for i in sents if not ('@$\t' in i or '#' in i)] 

Jeśli chcesz tylko rzeczy, które zaczynają z wymienionych zdań użyć metody str.startswith(stringOfInterest)

+2

Powiedziałbym, że ten jest lepszy niż pozostałe dwa, ponieważ nie zakładają, że podciągi są na początku – Frikster

9

Inną techniką z użyciem filter

filter(lambda s: not (s[0:3]=="@$\t" or s[0]=="#"), sents) 

Problem z twoim orignal approac h oznacza, że ​​znajdujesz się na pozycji listy i i że należy ją usunąć, usuń ją z listy, która przesuwa element i+1 do pozycji do pozycji i. Następna iteracja pętli znajduje się w indeksie i+1, ale pozycja jest w rzeczywistości i+2.

Sens?

+0

dzięki za wyjaśnienie! popping listy podczas wyliczania jest naprawdę głupie. hahaha .. – alvas

+0

+1 za wyjaśnienie problemu. – abarnert