Removendo uma lista de caracteres na string

217

Eu quero remover caracteres em uma string em python:

string.replace(',', '').replace("!", '').replace(":", '').replace(";", '')...

Mas tenho muitos caracteres que tenho que remover. Pensei em uma lista

list = [',', '!', '.', ';'...]

Mas como posso usar o listpara substituir os caracteres no string?

Laura
fonte
6
Consulte stackoverflow.com/questions/1919096/… para obter várias soluções e uma boa comparação.
Martijn de Milliano 04/04
É uma pena que o Python (que é fornecido com as baterias incluídas) não lide com esse caso de uso imediatamente. A função str_replace do PHP faz isso - você pode passar uma matriz como o primeiro argumento e uma string como o segundo ( php.net/manual/pl/function.str-replace.php ).
precisa saber é o seguinte

Respostas:

264

Se você estiver usando python2 e suas entradas forem strings (não unicodes), o melhor método é str.translate:

>>> chars_to_remove = ['.', '!', '?']
>>> subj = 'A.B!C?'
>>> subj.translate(None, ''.join(chars_to_remove))
'ABC'

Caso contrário, existem as seguintes opções a serem consideradas:

A. Iterate o assunto char por char, omita caracteres indesejados e joina lista resultante:

>>> sc = set(chars_to_remove)
>>> ''.join([c for c in subj if c not in sc])
'ABC'

(Observe que a versão do gerador ''.join(c for c ...)será menos eficiente).

B. Crie uma expressão regular em tempo real e re.subcom uma string vazia:

>>> import re
>>> rx = '[' + re.escape(''.join(chars_to_remove)) + ']'
>>> re.sub(rx, '', subj)
'ABC'

( re.escapegarante que os caracteres gostem ^ou ]não quebrem a expressão regular).

C. Use a variante de mapeamento detranslate :

>>> chars_to_remove = [u'δ', u'Γ', u'ж']
>>> subj = u'AжBδCΓ'
>>> dd = {ord(c):None for c in chars_to_remove}
>>> subj.translate(dd)
u'ABC'

Código de teste completo e horários:

#coding=utf8

import re

def remove_chars_iter(subj, chars):
    sc = set(chars)
    return ''.join([c for c in subj if c not in sc])

def remove_chars_re(subj, chars):
    return re.sub('[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_re_unicode(subj, chars):
    return re.sub(u'(?u)[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_translate_bytes(subj, chars):
    return subj.translate(None, ''.join(chars))

def remove_chars_translate_unicode(subj, chars):
    d = {ord(c):None for c in chars}
    return subj.translate(d)

import timeit, sys

def profile(f):
    assert f(subj, chars_to_remove) == test
    t = timeit.timeit(lambda: f(subj, chars_to_remove), number=1000)
    print ('{0:.3f} {1}'.format(t, f.__name__))

print (sys.version)
PYTHON2 = sys.version_info[0] == 2

print ('\n"plain" string:\n')

chars_to_remove = ['.', '!', '?']
subj = 'A.B!C?' * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)
profile(remove_chars_re)

if PYTHON2:
    profile(remove_chars_translate_bytes)
else:
    profile(remove_chars_translate_unicode)

print ('\nunicode string:\n')

if PYTHON2:
    chars_to_remove = [u'δ', u'Γ', u'ж']
    subj = u'AжBδCΓ'
else:
    chars_to_remove = ['δ', 'Γ', 'ж']
    subj = 'AжBδCΓ'

subj = subj * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)

if PYTHON2:
    profile(remove_chars_re_unicode)
else:
    profile(remove_chars_re)

profile(remove_chars_translate_unicode)

Resultados:

2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]

"plain" string:

0.637 remove_chars_iter
0.649 remove_chars_re
0.010 remove_chars_translate_bytes

unicode string:

0.866 remove_chars_iter
0.680 remove_chars_re_unicode
1.373 remove_chars_translate_unicode

---

3.4.2 (v3.4.2:ab2c023a9432, Oct  5 2014, 20:42:22) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]

"plain" string:

0.512 remove_chars_iter
0.574 remove_chars_re
0.765 remove_chars_translate_unicode

unicode string:

0.817 remove_chars_iter
0.686 remove_chars_re
0.876 remove_chars_translate_unicode

(Como uma observação lateral, o número para remove_chars_translate_bytespode nos dar uma pista de por que o setor estava relutante em adotar o Unicode por tanto tempo).

georg
fonte
1
O segundo método gera um erro TypeError: translate() takes exactly one argument (2 given). Aparentemente, toma o ditado como argumento.
antonavy
@antonavy - a 2ª solução funciona - mas apenas da corda não é unicode (para o qual um diferente traduzir () é necessário)
FuzzyAmi
112

Você pode usar str.translate():

s.translate(None, ",!.;")

Exemplo:

>>> s = "asjo,fdjk;djaso,oio!kod.kjods;dkps"
>>> s.translate(None, ",!.;")
'asjofdjkdjasooiokodkjodsdkps'
Sven Marnach
fonte
19
@ thg435: Ninguém pediu isso, mas mesmo assim:s.translate(dict.fromkeys(map(ord, u",!.;")))
Sven Marnach
2
Essa resposta simultânea (e da @ PraveenGollakota) é exatamente o que a @Laura pediu e deve ser a (s) resposta (s) preferida (s).
hobs
7
porque python3: TypeError: translate () leva exatamente um argumento (2 dado)
Gank
2
@ Gank: O unicode.translate()método possui parâmetros diferentes do str.translate()método. Use a variante no comentário acima para objetos Unicode.
Sven Marnach 19/09/2015
@SvenMarnach, o que é mapa (ord, u ",!.;"))? e você representa unicode?
precisa saber é o seguinte
34

Você pode usar o método de conversão .

s.translate(None, '!.;,')
Praveen Gollakota
fonte
16
''.join(c for c in myString if not c in badTokens)
ninjagecko
fonte
Útil em casos semelhantes, não baseados em caracteres e seqüências de caracteres +1
Wolf
12

Se você estiver usando python3 e procurando a translatesolução - a função foi alterada e agora assume 1 parâmetro em vez de 2.

Esse parâmetro é uma tabela (pode ser dicionário) em que cada chave é o ordinal Unicode (int) do caractere a ser encontrado e o valor é a substituição (pode ser um ordinal Unicode ou uma string para a qual mapear a chave).

Aqui está um exemplo de uso:

>>> list = [',', '!', '.', ';']
>>> s = "This is, my! str,ing."
>>> s.translate({ord(x): '' for x in list})
'This is my string'
Dekel
fonte
8

Outra abordagem usando regex:

''.join(re.split(r'[.;!?,]', s))
Alan
fonte
7

Por que não um loop simples?

for i in replace_list:
    string = string.replace(i, '')

Além disso, evite nomear listas 'list'. Ele substitui a função interna list.

aIKid
fonte
6

você poderia usar algo assim

def replace_all(text, dic):
  for i, j in dic.iteritems():
    text = text.replace(i, j)
  return text

Esse código não é meu e vem daqui, é um ótimo artigo e discute em profundidade isso

honra do krystan
fonte
3

Também um tópico interessante sobre a remoção de sotaque UTF-8 forma uma string que converte char para seu char não acentuado padrão:

Qual é a melhor maneira de remover acentos em uma string unicode python?

extração de código do tópico:

import unicodedata

def remove_accents(input_str):
    nkfd_form = unicodedata.normalize('NFKD', input_str)
    return u"".join([c for c in nkfd_form if not unicodedata.combining(c)])
Sylvain
fonte
3

Talvez uma maneira mais moderna e funcional de alcançar o que você deseja:

>>> subj = 'A.B!C?'
>>> list = set([',', '!', '.', ';', '?'])
>>> filter(lambda x: x not in list, subj)
'ABC'

observe que, para esse fim específico, é um exagero, mas quando você precisar de condições mais complexas, o filtro será útil

tumultuado
fonte
Observe também que isso pode ser feito facilmente com a compreensão de listas, o que é muito mais pitônico na minha opinião.
tumultuou
3

maneira simples,

import re
str = 'this is string !    >><< (foo---> bar) @-tuna-#   sandwich-%-is-$-* good'

// condense multiple empty spaces into 1
str = ' '.join(str.split()

// replace empty space with dash
str = str.replace(" ","-")

// take out any char that matches regex
str = re.sub('[!@#$%^&*()_+<>]', '', str)

resultado:

this-is-string--foo----bar--tuna---sandwich--is---good

perfecto25
fonte
1

Que tal isso - um forro.

reduce(lambda x,y : x.replace(y,"") ,[',', '!', '.', ';'],";Test , ,  !Stri!ng ..")
Akshay Hazari
fonte
1

Eu acho que isso é bastante simples e servirá!

list = [",",",","!",";",":"] #the list goes on.....

theString = "dlkaj;lkdjf'adklfaj;lsd'fa'dfj;alkdjf" #is an example string;
newString="" #the unwanted character free string
for i in range(len(TheString)):
    if theString[i] in list:
        newString += "" #concatenate an empty string.
    else:
        newString += theString[i]

essa é uma maneira de fazer isso. Mas se você está cansado de manter uma lista de caracteres que deseja remover, você pode realmente fazê-lo usando o número do pedido das strings pelas quais itera. o número do pedido é o valor ascii desse caractere. o número ascii para 0 como um caractere é 48 e o número ascii para minúsculas z é 122, portanto:

theString = "lkdsjf;alkd8a'asdjf;lkaheoialkdjf;ad"
newString = ""
for i in range(len(theString)):
     if ord(theString[i]) < 48 or ord(theString[i]) > 122: #ord() => ascii num.
         newString += ""
     else:
        newString += theString[i]
Hiskel Kelemework
fonte
0

Atualmente, estou mergulhando em um esquema e agora acho que sou bom em recorrer e avaliar. HAHAHA. Apenas compartilhe algumas novas maneiras:

primeiro, avalie

print eval('string%s' % (''.join(['.replace("%s","")'%i for i in replace_list])))

segundo, recursá-lo

def repn(string,replace_list):
    if replace_list==[]:
        return string
    else:
        return repn(string.replace(replace_list.pop(),""),replace_list)

print repn(string,replace_list)

Ei, não faça voto negativo. Eu só quero compartilhar uma nova idéia.

tcpiper
fonte
0

Estou pensando em uma solução para isso. Primeiro, eu faria a entrada da string como uma lista. Então eu substituiria os itens da lista. Então, usando o comando join, retornarei a lista como uma string. O código pode ser assim:

def the_replacer(text):
    test = []    
    for m in range(len(text)):
        test.append(text[m])
        if test[m]==','\
        or test[m]=='!'\
        or test[m]=='.'\
        or test[m]=='\''\
        or test[m]==';':
    #....
            test[n]=''
    return ''.join(test)

Isso removeria qualquer coisa da string. O que você acha disso?

Sheikh Ahmad Shah
fonte
0

Aqui está uma more_itertoolsabordagem:

import more_itertools as mit


s = "A.B!C?D_E@F#"
blacklist = ".!?_@#"

"".join(mit.flatten(mit.split_at(s, pred=lambda x: x in set(blacklist))))
# 'ABCDEF'

Aqui, dividimos os itens encontrados em blacklist, achatamos os resultados e juntamos a string.

pylang
fonte
0

Python 3, implementação de compreensão de lista de linha única.

from string import ascii_lowercase # 'abcdefghijklmnopqrstuvwxyz'
def remove_chars(input_string, removable):
  return ''.join([_ for _ in input_string if _ not in removable])

print(remove_chars(input_string="Stack Overflow", removable=ascii_lowercase))
>>> 'S O'
John Forbes
fonte
0

Remover *%,&@! abaixo da string:

s = "this is my string,  and i will * remove * these ** %% "
new_string = s.translate(s.maketrans('','','*%,&@!'))
print(new_string)

# output: this is my string  and i will  remove  these  
Biplob Das
fonte