58

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

前:

sd67637 8

后:

676378

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

4

7 回答 7

101

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

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

print result
>>> '78347834745'
于 2013-06-27T07:52:27.650 回答
27

逐个字符地循环遍历您的字符串,并且仅包含数字:

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)
于 2013-06-27T07:20:54.147 回答
10

有一个内置的。

string.translate(s, table[, deletechars])

从 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'
于 2013-06-27T07:36:31.130 回答
1

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

from string import *

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

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

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

于 2013-06-27T07:28:50.477 回答
1

我不会为此使用 RegEx。它慢了很多!

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

TLDR;

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

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

说明

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

  1. For循环方法(我的想法)。
  2. 来自Jon Clements 的答案的列表理解方法。
  3. Moradnejad 的回答中的RegEx 方法。
# 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 快四倍以上,大约是理解方法的两倍。有时简单是最好的。

于 2021-11-29T22:01:17.360 回答
0

提取整数

示例:sd67637 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)
于 2021-08-05T17:08:56.527 回答
0

添加到 @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]

于 2021-10-16T17:55:28.240 回答