Program Club

Python의 문자열에서 숫자가 아닌 모든 문자 ( "."제외)를 제거합니다.

proclub 2020. 12. 6. 22:15
반응형

Python의 문자열에서 숫자가 아닌 모든 문자 ( "."제외)를 제거합니다.


나는 꽤 잘 작동하는 코드를 가지고 있지만 누군가가 이것을 수행하는 방법에 대해 더 나은 제안이 있는지 궁금합니다.

val = ''.join([c for c in val if c in '1234567890.'])

당신은 무엇을 하시겠습니까?


정규식 ( re모듈 사용)을 사용하여 동일한 작업을 수행 할 수 있습니다. 아래 예는 [^\d.](십진수 또는 마침표가 아닌 모든 문자)의 실행을 일치 시키고 빈 문자열로 바꿉니다. 패턴이 UNICODE플래그 로 컴파일 된 경우 결과 문자열에는 여전히 비 ASCII 숫자가 포함될 수 있습니다 . 또한 "숫자가 아닌"문자를 제거한 후 결과가 반드시 유효한 숫자는 아닙니다.

>>> import re
>>> non_decimal = re.compile(r'[^\d.]+')
>>> non_decimal.sub('', '12.34fe4e')
'12.344'

또 다른 '파이썬'접근법

filter( lambda x: x in '0123456789.', s )

그러나 정규식이 더 빠릅니다.


다음은 몇 가지 샘플 코드입니다.

$ cat a.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join([c for c in a if c in '1234567890.'])

$ cat b.py
import re

non_decimal = re.compile(r'[^\d.]+')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    non_decimal.sub('', a)

$ cat c.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join([c for c in a if c.isdigit() or c == '.'])

$ cat d.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    b = []
    for c in a:
        if c.isdigit() or c == '.': continue
        b.append(c)

    ''.join(b)

그리고 타이밍 결과 :


$ time python a.py
real    0m24.735s
user    0m21.049s
sys     0m0.456s

$ time python b.py
real    0m10.775s
user    0m9.817s
sys     0m0.236s

$ time python c.py
real    0m38.255s
user    0m32.718s
sys     0m0.724s

$ time python d.py
real    0m46.040s
user    0m41.515s
sys     0m0.832s

Looks like the regex is the winner so far.

Personally, I find the regex just as readable as the list comprehension. If you're doing it just a few times then you'll probably take a bigger hit on compiling the regex. Do what jives with your code and coding style.


A simple solution is to use regular expessions

import re 
re.sub("[^0-9^.]", "", data)

import string
filter(lambda c: c in string.digits + '.', s)

If the set of characters were larger, using sets as below might be faster. As it is, this is a bit slower than a.py.

dec = set('1234567890.')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join(ch for ch in a if ch in dec)

At least on my system, you can save a tiny bit of time (and memory if your string were long enough to matter) by using a generator expression instead of a list comprehension in a.py:

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join(c for c in a if c in '1234567890.')

Oh, and here's the fastest way I've found by far on this test string (much faster than regex) if you are doing this many, many times and are willing to put up with the overhead of building a couple of character tables.

chrs = ''.join(chr(i) for i in xrange(256))
deletable = ''.join(ch for ch in chrs if ch not in '1234567890.')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    a.translate(chrs, deletable)

On my system, that runs in ~1.0 seconds where the regex b.py runs in ~4.3 seconds.

참고URL : https://stackoverflow.com/questions/947776/strip-all-non-numeric-characters-except-for-from-a-string-in-python

반응형