Como remover substrings específicos de um conjunto de strings em Python?

160

Eu tenho um conjunto de strings set1, e todas as strings set1possuem duas substrings específicas que eu não preciso e quero remover.
Entrada de amostra: set1={'Apple.good','Orange.good','Pear.bad','Pear.good','Banana.bad','Potato.bad'}
Então, basicamente, quero que as substrings .goode sejam .badremovidas de todas as strings.
O que eu tentei:

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

Mas isso parece não funcionar. Não há absolutamente nenhuma alteração na saída e é igual à entrada. Eu tentei usar em for x in list(set1)vez do original, mas isso não muda nada.

controlfreak
fonte

Respostas:

187

Strings são imutáveis. string.replace(python 2.x) ou str.replace(python 3.x) cria uma nova string. Isto é afirmado na documentação:

Retorne uma cópia da string s com todas as ocorrências de substring antigas substituídas por novas. ...

Isso significa que você deve realocar o conjunto ou realimentá-lo novamente (a alocação é mais fácil com a compreensão do conjunto) :

new_set = {x.replace('.good', '').replace('.bad', '') for x in set1}
Reut Sharabani
fonte
3
string.replace()foi preterido no python 3.x, agora éstr.replace()
Yossarian42
71
>>> x = 'Pear.good'
>>> y = x.replace('.good','')
>>> y
'Pear'
>>> x
'Pear.good'

.replacenão altera a string, ele retorna uma cópia da string com a substituição. Você não pode alterar a string diretamente, porque as strings são imutáveis.

Você precisa pegar os valores de retorno x.replacee colocá-los em um novo conjunto.

Alex Hall
fonte
Mas quando eu faço um loop sobre o conjunto de cadeias, como posso atualizar um novo conjunto? usando set_name.update? Você poderia mostrar isso?
Controlfreak
12

Tudo que você precisa é de um pouco de magia negra!

>>> a = ["cherry.bad","pear.good", "apple.good"]
>>> a = list(map(lambda x: x.replace('.good','').replace('.bad',''),a))
>>> a
['cherry', 'pear', 'apple']
gueeest
fonte
5

Você pode fazer isso:

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
fonte
2
linha x.replace('.good',' ')e x.replace('.bad',' ')não faz nada com o resultado final. A impressão será a mesma sem eles.
Srđan Popić 16/02
Também eu preferiria ter apenas uma linha com re.sub, assim:x = re.sub('((\.good$)|(\.bad$))', '', x)
Srđan Popić
@ SrđanPopić Sim, eu concordo com você
Vivek
devemos editá-lo de acordo? (remove replaces e mover tudo para uma re.subchamada)
Srđan Popic
1
@ SrđanPopić Postei esta resposta porque é simples e passo a passo.
Vivek
3

Fiz o teste (mas não é o seu exemplo) e os dados não os retornam em ordem ou estão completos

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

Eu provei que isso funciona:

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

ou

>>> 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
fonte
3

Quando há várias substrings a serem removidas, uma opção simples e eficaz é usar re.subcom um padrão compilado que envolve a união de todas as substrings a serem removidas usando o |tubo regex 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
fonte
1

Se lista

Eu estava fazendo algo para uma lista que é um conjunto de seqüências de caracteres e você deseja remover todas as linhas que possuem uma certa substring, você pode fazer isso

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

onde subestá um padrão que você não deseja ter em uma lista de linhasLinSplitUnOr

por exemplo

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

Então Aserá

insira a descrição da imagem aqui

rsc05
fonte
0

se você excluir algo da lista, você poderá usar desta forma: (o método sub diferencia maiúsculas de minúsculas)

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
fonte