@JG: Eu tenho gtk.Entry () e quero multiplicar float inserido nele.
Jan Tojnar
1
@JanTojnar usa o método re.sub conforme a resposta dois e lista explicitamente quais caracteres devem ser mantidos, por exemplo, re.sub ("[^ 0123456789 \.]", "", "Poo123.4and5fish")
Roger Heathcote -
Respostas:
112
No Python 2. *, de longe a abordagem mais rápida é o .translatemétodo:
string.maketranscria uma tabela de conversão (uma string de comprimento 256) que, neste caso, é a mesma que ''.join(chr(x) for x in range(256))(apenas mais rápida de fazer ;-). .translateaplica a tabela de conversão (que aqui é irrelevante, pois allsignifica essencialmente identidade) E exclui os caracteres presentes no segundo argumento - a parte principal.
.translatefunciona de forma muito diferente em cadeias de caracteres Unicode (e strings em Python 3 - I fazer perguntas desejo especificado que grande-lançamento do Python é de interesse!) - não é tão simples, não é bem isso rápido, embora ainda bastante utilizável.
De volta a 2. *, a diferença de desempenho é impressionante ...:
$ python -mtimeit -s'import string; all=string.maketrans("", ""); nodig=all.translate(all, string.digits); x="aaa12333bb445bb54b5b52"''x.translate(all, nodig)'1000000 loops, best of 3:1.04 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"''re.sub(r"\D", "", x)'100000 loops, best of 3:7.9 usec per loop
Acelerar as coisas em 7-8 vezes dificilmente é um amendoim, portanto translatevale a pena conhecer e usar o método. A outra abordagem popular não-ER ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"''"".join(i for i in x if i.isdigit())'100000 loops, best of 3:11.5 usec per loop
é 50% mais lento que ER, então a .translateabordagem supera-a em uma ordem de magnitude.
No Python 3 ou no Unicode, você precisa passar .translateum mapeamento (com ordinais, não caracteres diretamente, como chaves) que retorna Nonepara o que você deseja excluir. Aqui está uma maneira conveniente de expressar isso para excluir "tudo menos" alguns caracteres:
import string
classDel:def __init__(self, keep=string.digits):
self.comp = dict((ord(c),c)for c in keep)def __getitem__(self, k):return self.comp.get(k)
DD =Del()
x='aaa12333bb445bb54b5b52'
x.translate(DD)
também emite '1233344554552'. No entanto, colocando isso no xx.py, temos ...:
$ python3.1-mtimeit -s'import re; x="aaa12333bb445bb54b5b52"''re.sub(r"\D", "", x)'100000 loops, best of 3:8.43 usec per loop
$ python3.1-mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"''x.translate(xx.DD)'10000 loops, best of 3:24.3 usec per loop
... que mostra que a vantagem de desempenho desaparece para esse tipo de "exclusão" de tarefas e se torna uma diminuição de desempenho.
@sunqiang, sim, absolutamente - há uma razão pela qual o Py3k foi para o Unicode como o tipo de string de texto, em vez de por bytes como no Py2 - pela mesma razão que Java e C # sempre tiveram o mesmo meme "string significa unicode" ... algumas despesas gerais, talvez, mas MUITO melhor suporte para praticamente qualquer coisa, menos inglês! -).
Alex Martelli
29
x.translate(None, string.digits)na verdade resulta em 'aaabbbbbb', que é o oposto do que se destina.
26612 Tom Dalling
4
Ecoando os comentários de Tom Dalling, seu primeiro exemplo mantém todos os personagens indesejáveis - faz o oposto do que você disse.
Chris Johnson
3
@ RyanB.Lynch et al., A culpa foi de um editor posterior e de outros dois usuários que aprovaram a edição , que, de fato, está totalmente errada. Revertido.
Nick T
1
substituindo allbuiltin ... não tenho certeza sobre isso!
Andy Hayden
197
Use re.sub, assim:
>>>import re
>>> re.sub('\D','','aas30dsa20')'3020'
\D corresponde a qualquer caractere que não seja um dígito, portanto, o código acima substitui essencialmente todos os caracteres que não são dígitos da string vazia.
Ou você pode usar filter, assim (no Python 2):
>>> filter(str.isdigit,'aas30dsa20')'3020'
Como no Python 3, filterretorna um iterador em vez de a list, você pode usar o seguinte:
re é mau em uma tarefa tão simples, a segunda é a melhor que penso, porque os métodos 'is ...' são os mais rápidos para as strings.
F0b0s
seu exemplo de filtro é limitado a py2k
SilentGhost 20/09/2009
2
@ f0b0s-iu9-info: você cronometrou? na minha máquina (Py3k) Re é duas vezes mais rápido do que com filtro isdigit, com gerador isdigtestá a meio caminho entre eles
SilentGhost
@ SilentGhost: Obrigado, eu estava usando o IDLE do py2k. Está consertado agora.
João Silva
1
@asmaier Simplesmente use rpara string bruta:re.sub(r"\D+", "", "aas30dsa20")
Recebo um TypeError: translate () leva exatamente um argumento (2 dados). Por que essa pergunta foi votada em seu estado atual é bastante frustrante.
Bobort
conversão alterada do python 2 para 3. A sintaxe que usa esse método no python 3 é x.translate (str.maketrans ('', '', string.digits)) e x.translate (str.maketrans ('', '' , string.ascii_letters)). Nenhuma dessas faixas de espaço em branco. Eu realmente não recomendo essa abordagem mais ...
ZaxR
5
A opção menciona nos comentários que ele deseja manter a casa decimal. Isso pode ser feito com o método re.sub (conforme a segunda e melhor resposta do IMHO) listando explicitamente os caracteres a serem mantidos, por exemplo
No meu código eu verificar o número de períodos na cadeia de entrada e gerar um erro se isso é mais do que 1.
Roger Heathcote
4
Uma versão rápida para Python 3:
# xx3.pyfrom collections import defaultdict
import string
_NoneType= type(None)def keeper(keep):
table = defaultdict(_NoneType)
table.update({ord(c): c for c in keep})return table
digit_keeper = keeper(string.digits)
Aqui está uma comparação de desempenho versus regex:
$ python3.3-mtimeit -s'import xx3; x="aaa12333bb445bb54b5b52"''x.translate(xx3.digit_keeper)'1000000 loops, best of 3:1.02 usec per loop
$ python3.3-mtimeit -s'import re; r = re.compile(r"\D"); x="aaa12333bb445bb54b5b52"''r.sub("", x)'100000 loops, best of 3:3.43 usec per loop
Então, é um pouco mais de três vezes mais rápido que o regex, para mim. Também é mais rápido do que o class Delanterior, porque defaultdictfaz todas as suas pesquisas em C, em vez de (lento) Python. Aqui está essa versão no meu mesmo sistema, para comparação.
$ python3.3-mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"''x.translate(xx.DD)'100000 loops, best of 3:13.6 usec per loop
@SilentGhost é o meu mal-entendido. tinha corrigido graças :)
Gant
Na verdade, com esse método, não acho que você precise usar "join". filter(lambda x: x.isdigit(), s)funcionou bem para mim. ... ah, é porque eu estou usando o Python 2.7.
Respostas:
No Python 2. *, de longe a abordagem mais rápida é o
.translate
método:string.maketrans
cria uma tabela de conversão (uma string de comprimento 256) que, neste caso, é a mesma que''.join(chr(x) for x in range(256))
(apenas mais rápida de fazer ;-)..translate
aplica a tabela de conversão (que aqui é irrelevante, poisall
significa essencialmente identidade) E exclui os caracteres presentes no segundo argumento - a parte principal..translate
funciona de forma muito diferente em cadeias de caracteres Unicode (e strings em Python 3 - I fazer perguntas desejo especificado que grande-lançamento do Python é de interesse!) - não é tão simples, não é bem isso rápido, embora ainda bastante utilizável.De volta a 2. *, a diferença de desempenho é impressionante ...:
Acelerar as coisas em 7-8 vezes dificilmente é um amendoim, portanto
translate
vale a pena conhecer e usar o método. A outra abordagem popular não-ER ...:é 50% mais lento que ER, então a
.translate
abordagem supera-a em uma ordem de magnitude.No Python 3 ou no Unicode, você precisa passar
.translate
um mapeamento (com ordinais, não caracteres diretamente, como chaves) que retornaNone
para o que você deseja excluir. Aqui está uma maneira conveniente de expressar isso para excluir "tudo menos" alguns caracteres:também emite
'1233344554552'
. No entanto, colocando isso no xx.py, temos ...:... que mostra que a vantagem de desempenho desaparece para esse tipo de "exclusão" de tarefas e se torna uma diminuição de desempenho.
fonte
x.translate(None, string.digits)
na verdade resulta em'aaabbbbbb'
, que é o oposto do que se destina.all
builtin ... não tenho certeza sobre isso!Use
re.sub
, assim:\D
corresponde a qualquer caractere que não seja um dígito, portanto, o código acima substitui essencialmente todos os caracteres que não são dígitos da string vazia.Ou você pode usar
filter
, assim (no Python 2):Como no Python 3,
filter
retorna um iterador em vez de alist
, você pode usar o seguinte:fonte
isdigit
, com geradorisdigt
está a meio caminho entre elesr
para string bruta:re.sub(r"\D+", "", "aas30dsa20")
Outra variante do gerador.
fonte
Você pode usar o filtro:
No python3.0 você tem que se juntar a isso (meio feio :()
fonte
str
paralist
garantir que ele funcione em py2 e py3:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
na linha da resposta da bayer:
fonte
-
não é um dígito.Você pode fazer isso facilmente usando o Regex
fonte
excluirá todos os dígitos da string. Para excluir letras e manter os dígitos, faça o seguinte:
fonte
TypeError
: translate () leva exatamente um argumento (2 dados). Por que essa pergunta foi votada em seu estado atual é bastante frustrante.A opção menciona nos comentários que ele deseja manter a casa decimal. Isso pode ser feito com o método re.sub (conforme a segunda e melhor resposta do IMHO) listando explicitamente os caracteres a serem mantidos, por exemplo
fonte
Uma versão rápida para Python 3:
Aqui está uma comparação de desempenho versus regex:
Então, é um pouco mais de três vezes mais rápido que o regex, para mim. Também é mais rápido do que o
class Del
anterior, porquedefaultdict
faz todas as suas pesquisas em C, em vez de (lento) Python. Aqui está essa versão no meu mesmo sistema, para comparação.fonte
Use uma expressão geradora:
fonte
''.join(n for n in foo if n.isdigit())
Feio, mas funciona:
fonte
list(s)
?filter(lambda x: x.isdigit(), s)
funcionou bem para mim. ... ah, é porque eu estou usando o Python 2.7.Eu tinha observado que a junção é mais rápida que a sub.
fonte
Você pode ler cada personagem. Se for dígito, inclua-o na resposta. O
str.isdigit()
método é uma maneira de saber se um caractere é um dígito.fonte
Não é um liner, mas muito simples:
fonte
Eu usei isso.
'letters'
deve conter todas as letras das quais você deseja se livrar:Output = Input.translate({ord(i): None for i in 'letters'}))
Exemplo:
Input = "I would like 20 dollars for that suit" Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'})) print(Output)
Resultado:
20
fonte