Jak usunąć określone podciągi z zestawu ciągów w Pythonie?

160

Mam zestaw ciągów set1, a wszystkie z nich set1mają dwa określone podciągi, których nie potrzebuję i chcę usunąć.
Przykładowe dane wejściowe: set1={'Apple.good','Orange.good','Pear.bad','Pear.good','Banana.bad','Potato.bad'}
Więc w zasadzie chcę usunąć podciągi .goodi .badze wszystkich ciągów.
Co próbowałem:

for x in set1:
    x.replace('.good','')
    x.replace('.bad','')

Ale to w ogóle nie działa. Nie ma absolutnie żadnej zmiany na wyjściu i jest to to samo, co wejście. Próbowałem użyć for x in list(set1)zamiast oryginalnego, ale to niczego nie zmienia.

controlfreak
źródło

Odpowiedzi:

187

Ciągi znaków są niezmienne. string.replace(python 2.x) lub str.replace(python 3.x) tworzy nowy ciąg. Jest to określone w dokumentacji:

Zwraca kopię łańcucha s ze wszystkimi wystąpieniami podłańcucha starego zamienionego na nowy. ...

Oznacza to, że musisz ponownie przydzielić zestaw lub ponownie go wypełnić (ponowne przydzielenie jest łatwiejsze dzięki zrozumieniu zestawu) :

new_set = {x.replace('.good', '').replace('.bad', '') for x in set1}
Reut Sharabani
źródło
3
string.replace()jest przestarzałe w Pythonie 3.x, teraz jeststr.replace()
Yossarian42
71
>>> x = 'Pear.good'
>>> y = x.replace('.good','')
>>> y
'Pear'
>>> x
'Pear.good'

.replacenie zmienia ciągu, zwraca kopię ciągu z zamiennikiem. Nie możesz zmienić ciągu bezpośrednio, ponieważ są one niezmienne.

Musisz pobrać wartości zwracane z x.replacei umieścić je w nowym zestawie.

Alex Hall
źródło
Ale kiedy zapętlę zestaw ciągów, jak mogę zaktualizować nowy zestaw? używając set_name.update? Czy możesz to pokazać?
controlfreak
12

Wystarczy odrobina czarnej magii!

>>> a = ["cherry.bad","pear.good", "apple.good"]
>>> a = list(map(lambda x: x.replace('.good','').replace('.bad',''),a))
>>> a
['cherry', 'pear', 'apple']
gueeest
źródło
5

Możesz to zrobić:

import re
import string
set1={'Apple.good','Orange.good','Pear.bad','Pear.good','Banana.bad','Potato.bad'}

for x in set1:
    x.replace('.good',' ')
    x.replace('.bad',' ')
    x = re.sub('\.good$', '', x)
    x = re.sub('\.bad$', '', x)
    print(x)
Vivek
źródło
2
line x.replace('.good',' ')i x.replace('.bad',' ')nie wpływa na efekt końcowy. Wydruk będzie taki sam bez nich.
Srđan Popić
Wolałbym też mieć tylko jedną linijkę re.sub, taką jak ta:x = re.sub('((\.good$)|(\.bad$))', '', x)
Srđan Popić
@ SrđanPopić tak Zgadzam się z tobą
Vivek
czy powinniśmy go odpowiednio edytować? (usuń replacesi i przenieś wszystko do jednej re.subrozmowy)
Srđan Popić
1
@ SrđanPopić Publikuję tę odpowiedź, ponieważ jest prosta i mądra krok po kroku.
Vivek
3

Zrobiłem test (ale to nie jest twój przykład) i dane nie zwracają ich uporządkowanych lub kompletnych

>>> ind = ['p5','p1','p8','p4','p2','p8']
>>> newind = {x.replace('p','') for x in ind}
>>> newind
{'1', '2', '8', '5', '4'}

Udowodniłem, że to działa:

>>> ind = ['p5','p1','p8','p4','p2','p8']
>>> newind = [x.replace('p','') for x in ind]
>>> newind
['5', '1', '8', '4', '2', '8']

lub

>>> newind = []
>>> ind = ['p5','p1','p8','p4','p2','p8']
>>> for x in ind:
...     newind.append(x.replace('p',''))
>>> newind
['5', '1', '8', '4', '2', '8']
user140259
źródło
3

Gdy istnieje wiele podciągów do usunięcia, jedną prostą i skuteczną opcją jest użycie re.subskompilowanego wzorca, który obejmuje połączenie wszystkich podciągów w celu usunięcia za pomocą |potoku wyrażenia regularnego OR ( ).

import re

to_remove = ['.good', '.bad']
strings = ['Apple.good','Orange.good','Pear.bad']

p = re.compile('|'.join(map(re.escape, to_remove))) # escape to handle metachars
[p.sub('', s) for s in strings]
# ['Apple', 'Orange', 'Pear']
cs95
źródło
1

Jeśli lista

Robiłem coś dla listy będącej zbiorem ciągów i chcesz usunąćwszystkie linie które mają określony podciąg możesz to zrobić

import re
def RemoveInList(sub,LinSplitUnOr):
    indices = [i for i, x in enumerate(LinSplitUnOr) if re.search(sub, x)]
    A = [i for j, i in enumerate(LinSplitUnOr) if j not in indices]
    return A

gdzie subjest wzór, którego nie chcesz mieć na liście liniiLinSplitUnOr

na przykład

A=['Apple.good','Orange.good','Pear.bad','Pear.good','Banana.bad','Potato.bad']
sub = 'good'
A=RemoveInList(sub,A)

Wtedy Abędzie

wprowadź opis obrazu tutaj

rsc05
źródło
0

jeśli usuniesz coś z listy, możesz użyć tego sposobu: (metoda sub rozróżnia wielkość liter)

new_list = []
old_list= ["ABCDEFG","HKLMNOP","QRSTUV"]

for data in old_list:
     new_list.append(re.sub("AB|M|TV", " ", data))

print(new_list) // output : [' CDEFG', 'HKL NOP', 'QRSTUV']
mamal
źródło