파이썬을 사용하여 문자열에서 숫자를 제외한 문자를 제거 하시겠습니까?


137

문자열에서 숫자를 제외한 모든 문자를 제거하려면 어떻게합니까?


@ Jan Tojnar : 예를 들어 줄 수 있습니까?
João Silva

@ JG : gtk.Entry ()가 있고 multiply float을 입력하고 싶습니다.
Jan Tojnar

1
@JanTojnar는 응답 2에 따라 re.sub 메소드를 사용하고 유지할 문자를 명시 적으로 나열합니다. 예 : re.sub ( "[^ 0123456789 \.]", "", "poo123.4and5fish")
Roger Heathcote

답변:


112

Python 2. *에서 가장 빠른 방법은 다음과 .translate같습니다.

>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>> 

string.maketrans이 경우 번역 테이블 (길이 256의 문자열) ''.join(chr(x) for x in range(256))을 만듭니다 ( 이 경우에는 더 빠름 ;-). .translate변환 테이블을 적용합니다 (여기서는 all본질적으로 ID를 의미 하므로 관련이 없음 ). 두 번째 인수 인 핵심 부분에있는 문자를 삭제합니다.

.translate매우 다르게 유니 코드 문자열에서 작동 (파이썬 3 문자열 - 내가 소원 질문 파이썬의 주요 릴리스가 관심 인 지정!) - 확실히이 간단한, 꽤 이렇게 빨리,하지만 아직도 확실히 가능.

2. *로 돌아 가면 성능 차이는 놀랍습니다 ... :

$ 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

7-8 배 빠르게 물건을 만드는 것은 땅콩이 거의 아니므로이 translate방법을 알고 사용하는 것이 좋습니다. 다른 인기있는 비 RE 접근 방식 :

$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop

RE보다 50 % 느리므로 .translate접근 방식이이를 훨씬 능가합니다.

Python 3 또는 유니 코드의 경우 삭제하려는 항목을 .translate리턴하는 맵핑 (문자가 아닌 서 수가있는 키)을 전달해야합니다 None. 다음은 "모든 것을 제외한"문자를 삭제하기 위해 이것을 표현하는 편리한 방법입니다.

import string

class Del:
  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)

또한 방출 '1233344554552'합니다. 그러나 이것을 xx.py에 넣으면 ... :

$ 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

... 이러한 "삭제"작업에 대한 성능 이점이 사라지고 성능이 저하됨을 나타냅니다.


1
@sunqiang, 예, 절대적으로-Py3k가 Py2에서와 같이 바이트 문자열 대신 텍스트 문자열 유형으로 유니 코드로 이동 한 이유가 있습니다 .Java와 C #은 항상 동일한 "문자열은 유니 코드"라는 밈을 가지고 있습니다 ... 약간의 오버 헤드 일 수도 있지만 영어 이외의 모든 것에 대한 지원이 훨씬 좋습니다!-).
Alex Martelli

29
x.translate(None, string.digits)실제로 결과 'aaabbbbbb'는 의도 한 것과 반대입니다.
Tom Dalling

4
Tom Dalling의 의견을 들려주는 첫 번째 예는 바람직하지 않은 모든 문자를 유지합니다.
Chris Johnson

3
@ RyanB.Lynch et al., 그 결점은 나중에 편집자와 그 편집승인 한 다른 두 명의 사용자에게 있었습니다. 되돌 렸습니다.
Nick T

1
all내장을 재정의하는 중 ... 확실하지 않습니다!
Andy Hayden

197

다음 re.sub과 같이 사용하십시오 .

>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'

\D 숫자가 아닌 문자와 일치하므로 위의 코드는 기본적으로 빈 문자열의 숫자가 아닌 모든 문자를 대체합니다.

또는 filter(Python 2에서) 다음과 같이 사용할 수 있습니다 .

>>> filter(str.isdigit, 'aas30dsa20')
'3020'

Python 3에서는 filtera 대신 반복자를 반환하므로 대신 list다음을 사용할 수 있습니다.

>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'

그런 간단한 작업에서 다시 악의적입니다. 두 번째 방법은 내가 생각하는 최고입니다.
f0b0s

필터 예제는 py2k
SilentGhost로

2
@ f0b0s-iu9-info : 시간을 정했습니까? 내 컴퓨터 (py3k)에서 re 필터를 사용하여 필터보다 두 배 빠릅니다 isdigit. 발전기 isdigt가 그들 사이에 중간입니다
SilentGhost

@SilentGhost : 고맙습니다. py2k의 IDLE을 사용하고있었습니다. 이제 수정되었습니다.
João Silva

1
@asmaier 간단하게 사용하는 r원시 문자열 :re.sub(r"\D+", "", "aas30dsa20")
미치 McMabers

64
s=''.join(i for i in s if i.isdigit())

다른 발전기 변형.


람다가 사용 된 경우 사망이 .. + 1겠습니까 더 나은되었습니다
Barath Ravikumar

17

필터를 사용할 수 있습니다 :

filter(lambda x: x.isdigit(), "dasdasd2313dsa")

python3.0에서는 이것을 결합해야합니다 (kinda ugly :()

''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))

py2k에서만, py3k에서는 발전기를 반환합니다
SilentGhost

변환 str할 수 list있는지가 py2와 py3 모두 작동하는지 :''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
루이스 C.

13

바이엘의 대답을 따라 :

''.join(i for i in s if i.isdigit())

아니요, 숫자 -가 아니므로 음수에는 작동 하지 않습니다.
Oli

12

정규식을 사용하여 쉽게 할 수 있습니다.

>>> import re
>>> re.sub("\D","","£70,000")
70000

가장 쉬운 방법
Iorek

5
이것은 7 년 전에 제공된 João Silva의 답변과 어떻게 다릅니 까?
jww

7
x.translate(None, string.digits)

문자열에서 모든 숫자를 삭제합니다. 문자를 삭제하고 숫자를 유지하려면 다음과 같이하십시오.

x.translate(None, string.letters)

3
나는 다음을 얻는다 TypeError: translate ()는 정확히 하나의 인수 (2 주어진)를 취합니다. 이 질문이 현재 상태에서 찬성되는 이유는 상당히 실망 스럽습니다.
Bobort

python 2에서 3으로 변환이 변경되었습니다. python 3에서이 메소드를 사용하는 구문은 x.translate (str.maketrans ( '', '', string.digits)) 및 x.translate (str.maketrans ( '', '')입니다. , string.ascii_letters)). 이 둘 중 어느 것도 공백을 제거하지 않습니다. 더 이상이 방법을 권장하지 않습니다 ...
ZaxR

5

op는 소수점 이하 자릿수를 유지하고 싶다는 의견을 언급합니다. 이것은 유지하기 위해 문자를 명시 적으로 나열하여 re.sub 메소드를 사용하여 수행 할 수 있습니다 (예 : 초당 및 IMHO 베스트 답변).

>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'

"poo123.4and.5fish"는 어떻습니까?
Jan Tojnar

내 코드에서 입력 문자열의 기간 수를 확인하고 1보다 큰 경우 오류가 발생합니다.
Roger Heathcote

4

Python 3의 빠른 버전 :

# xx3.py
from 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)

성능 비교와 정규식은 다음과 같습니다.

$ 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

그래서 그것은 정규 표현식보다 3 배 이상 빠릅니다. 파이썬보다 (느린) C가 아닌 C에서 모든 조회를 수행 class Del하기 때문에 위 보다 빠릅니다 defaultdict. 비교를 위해 동일한 시스템에 해당 버전이 있습니다.

$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop

3

생성기 표현식을 사용하십시오.

>>> s = "foo200bar"
>>> new_s = "".join(i for i in s if i in "0123456789")

대신''.join(n for n in foo if n.isdigit())
shxfee

2

추악하지만 작동합니다.

>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>

왜 그래 list(s)?
SilentGhost

@SilentGhost 그것은 나의 오해입니다. 고마워했다 :)
Gant

실제로이 방법을 사용하면 "join"을 사용할 필요가 없다고 생각합니다. filter(lambda x: x.isdigit(), s)나를 위해 잘 작동했습니다. ... 오, 파이썬 2.7을 사용하고 있기 때문입니다.
Bobort

1
$ python -mtimeit -s'import re;  x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'

루프 당 100000 개의 루프 (3 : 2.48 usec 이상)

$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'

100000 루프, 최고 3 : 2.02 루프 당 루프

$ python -mtimeit -s'import re;  x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'

루프 당 100000 개의 루프 (3 : 2.37 usec 이상)

$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'

루프 당 100000 개의 루프, 최고 3 : 1.97 usec

조인이 하위보다 빠릅니다.


왜 두 가지 방법을 두 번 반복합니까? 그리고 당신의 대답이 어떻게 받아 들여지는 것과 다른지 설명 할 수 있습니까?
Jan Tojnar

두 결과 모두 같은 결과를냅니다. 그러나 조인이 결과의 하위 방법보다 빠르다는 것을 보여주고 싶습니다.
AnilReddy

그들은 그렇지 않습니다. 코드는 반대입니다. 또한 네 가지 측정이 있지만 두 가지 방법 만 있습니다.
Jan Tojnar

1

각 문자를 읽을 수 있습니다. 숫자이면 답에 포함하십시오. 이 str.isdigit() 방법 은 문자가 숫자인지 확인하는 방법입니다.

your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'

이것은 f0b0s의 답변과 어떻게 다릅니 까? 가져올 추가 정보가있는 경우 해당 답변을 편집해야합니다.
chevybow

0

하나의 라이너는 아니지만 매우 간단합니다.

buffer = ""
some_str = "aas30dsa20"

for char in some_str:
    if not char.isdigit():
        buffer += char

print( buffer )

0

나는 이것을 사용했다. 'letters'제거하려는 모든 문자를 포함해야합니다.

Output = Input.translate({ord(i): None for i in 'letters'}))

예:

Input = "I would like 20 dollars for that suit" Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'})) print(Output)

산출: 20

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.