python-3.x 从字符串中删除非数字字符

bis0qfac  于 2022-11-19  发布在  Python
关注(0)|答案(9)|浏览(248)

我的任务是从文本文件或字符串中删除所有非数字字符(包括空格),然后在旧字符旁边打印新结果,例如:
之前:

sd67637 8

之后:

676378

由于我是一个初学者,我不知道从哪里开始这个任务。请帮助

dzhpxtsq

dzhpxtsq1#

我不会为此使用RegEx。它要慢得多!

相反,让我们使用一个简单的for循环。

顶级域名;

此功能将快速完成工作...

def filter_non_digits(string: str) -> str:
    result = ''
    for char in string:
        if char in '1234567890':
            result += char
    return result

解释

让我们创建一个非常基本的基准来测试已经提出的几种不同的方法。

  1. For循环方法(我的想法)。
    1.从Jon Clements的回答中列出理解方法。
  2. RegEx方法来自Moradnejad的回答。
# filters.py

import re

# For loop method
def filter_non_digits_for(string: str) -> str:
    result = ''
    for char in string:
        if char in '1234567890':
            result += char
    return result 

# Comprehension method
def filter_non_digits_comp(s: str) -> str:
    return ''.join(ch for ch in s if ch.isdigit())

# RegEx method
def filter_non_digits_re(string: str) -> str:
    return re.sub('[^\d]','', string)

现在我们已经实现了每种删除数字的方法,下面让我们对每种方法进行基准测试。
下面是一些非常基本的基准测试代码。但是,它可以给予我们很好地比较每种方法的性能。

# tests.py

import time, platform
from filters import filter_non_digits_re,
                    filter_non_digits_comp,
                    filter_non_digits_for

def benchmark_func(func):
    start = time.time()
    # the "_" in the number just makes it more readable
    for i in range(100_000):
        func('afes098u98sfe')
    end = time.time()
    return (end-start)/100_000

def bench_all():
    print(f'# System ({platform.system()} {platform.machine()})')
    print(f'# Python {platform.python_version()}\n')

    tests = [
        filter_non_digits_re,
        filter_non_digits_comp,
        filter_non_digits_for,
    ]

    for t in tests:
        duration = benchmark_func(t)
        ns = round(duration * 1_000_000_000)
        print(f'{t.__name__.ljust(30)} {str(ns).rjust(6)} ns/op')

if __name__ == "__main__":
    bench_all()

下面是基准测试代码的输出。

# System (Windows AMD64)
# Python 3.9.8

filter_non_digits_re             2920 ns/op
filter_non_digits_comp           1280 ns/op
filter_non_digits_for             660 ns/op

正如你所看到的,filter_non_digits_for()函数比使用RegEx快四倍多,大约是解析方法的两倍。有时简单是最好的。

zazmityj

zazmityj2#

您可以使用string.ascii_letters来识别非数字:

from string import *

a = 'sd67637 8'
a = a.replace(' ', '')

for i in ascii_letters:
    a = a.replace(i, '')

如果要替换冒号,请使用引号"而不是冒号'

mcdcgff0

mcdcgff03#

提取整数

  • 示例:sd 67637 8 ==〉676378*
import re
def extract_int(x):
    return re.sub('[^\d]','', x)

提取单个浮点数/整型数(可能是小数分隔符)

  • 示例:sd7512.sd23 ==〉7512.23*
import re
def extract_single_float(x):
    return re.sub('[^\d|\.]','', x)

提取多个浮点数/浮点数

  • 示例:123.2 xs12.28 4 ==〉[123.2,12.28,4]*
import re
def extract_floats(x):
    return re.findall("\d+\.\d+", x)
i5desfxk

i5desfxk4#

添加到@MoradneJad中。您可以使用下面的代码来提取整数值、浮点数甚至是有符号值。
a = re.findall(r"[-+]?\d*\.\d+|\d+", "Over th44e same pe14.1riod of time, p-0.8rices also rose by 82.8p")
然后,您可以使用map有效地将列表项转换为数字数据类型。
print(list(map(float, a)))
[44.0, 14.1, -0.8, 82.8]

qmb5sa22

qmb5sa225#

import re
result = re.sub('\D','','sd67637 8')

结果〉〉〉'676378'

vaqhlq81

vaqhlq816#

转换所有带或不带单位缩写的数字字符串。必须通过参数dec =','指明源字符串是十进制逗号表示法。可以转换为浮点数和整数。默认转换为浮点数,但将参数设置为Int =True,则结果为整数。自动识别可在md字典中编辑的单位缩写。关键是单位缩写,值是乘数。这样,这个函数的应用就无穷无尽了。结果总是一个你可以计算的数字。这种集所有功能于一体的方法不是最快的,但你再也不用担心了,它总是返回一个可靠的结果。

import re
'''
units: gr=grams, K=thousands, M=millions, B=billions, ms=mili-seconds, mt= metric-tonnes
'''
md = {'gr': 0.001, '%': 0.01, 'K': 1000, 'M': 1000000, 'B': 1000000000, 'ms': 0.001, 'mt': 1000}
seps = {'.': True, ',': False}
kl = list(md.keys())

def to_Float_or_Int(strVal, toInt=None, dec=None):
    toInt = False if toInt is None else toInt
    dec = '.' if dec is None else dec

    def chck_char_in_string(strVal):
        rs = None
        for el in kl:
            if el in strVal:
                rs = el
                break
        return rs

    if dec in seps.keys():
        dcp = seps[dec]
        strVal = strVal.strip()
        mpk = chck_char_in_string(strVal)
        mp = 1 if mpk is None else md[mpk]
        strVal = re.sub(r'[^\de.,-]+', '', strVal)
        if dcp:
           strVal = strVal.replace(',', '')
        else:
            strVal = strVal.replace('.', '')
            strVal = strVal.replace(',', '.')
        dcnm = float(strVal)
        dcnm = dcnm * mp
        dcnm = int(round(dcnm)) if toInt else dcnm
    else:
        print('wrong decimal separator')
        dcnm = None
    return dcnm

调用函数如下:

pvals = ['-123,456', '-45,145.01 K', '753,159.456', '1,000,000', '985 ms' , '888 745.23', '1.753 e-04']
cvals = ['-123,456', '1,354852M', '+10.000,12 gr', '-87,24%', '10,2K', '985 ms', '(mt) 0,475', ' ,159']
print('decimal point strings')
for val in pvals:
    result = to_Float_or_Int(val)
    print(result)
print()
print('decimal comma strings')
for val in cvals:
    result = to_Float_or_Int(val, dec=',')
    print(result)
exit()

输出结果:

decimal point strings
-123456.0
-45145010.0
753159.456
1000000.0
0.985
888745.23
0.0001753

decimal comma strings
-123.456
1354852.0
10.00012
-0.8724
10200.0
0.985
475.0
0.159
wrrgggsh

wrrgggsh7#

最简单的方法是使用正则表达式

import re
a = 'lkdfhisoe78347834 (())&/&745  '
result = re.sub('[^0-9]','', a)

print result
>>> '78347834745'
fzwojiic

fzwojiic8#

逐个字符循环字符串,并且只包含数字:

new_string = ''.join(ch for ch in your_string if ch.isdigit())

或者在字符串上使用正则表达式(如果在某个时候你想单独处理不连续的组)...

import re
s = 'sd67637 8' 
new_string = ''.join(re.findall(r'\d+', s))
# 676378

然后就print他们出来了:

print(old_string, '=', new_string)
ffvjumwh

ffvjumwh9#

有一个内置的。

字符串.translate(s,表[,删除字符])

从中删除deletechars中的所有字符(如果存在),然后使用table转换字符,table必须是一个256个字符的字符串,提供每个字符值的转换,并按其序号进行索引。如果table为None,则只执行字符删除步骤。

>>> import string
>>> non_numeric_chars = ''.join(set(string.printable) - set(string.digits))
>>> non_numeric_chars = string.printable[10:]  # more effective method. (choose one)
'sd67637 8'.translate(None, non_numeric_chars)
'676378'

或者,您可以在不导入的情况下执行此操作(但没有这样做的理由):

>>> chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> 'sd67637 8'.translate(None, chars)
'676378'

相关问题