Removing non numeric characters from a string

PythonPython 3.xPython 3.3

Python Problem Overview


I have been given the task to remove all non numeric characters including spaces from a either text file or string and then print the new result next to the old characters for example:

Before:

sd67637 8

After:

676378

As i am a beginner i do not know where to start with this task. Please Help

Python Solutions


Solution 1 - Python

The easiest way is with a regexp

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

print result
>>> '78347834745'

Solution 2 - Python

Loop over your string, char by char and only include digits:

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

Or use a regex on your string (if at some point you wanted to treat non-contiguous groups separately)...

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

Then just print them out:

print(old_string, '=', new_string)

Solution 3 - Python

There is a builtin for this.

> string.translate(s, table[, deletechars]) > > Delete all characters from s > that are in deletechars (if present), and then translate the > characters using table, which must be a 256-character string giving > the translation for each character value, indexed by its ordinal. If > table is None, then only the character deletion step is performed.

>>> 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'

Or you could do it with no imports (but there is no reason for this):

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

Solution 4 - Python

You can use string.ascii_letters to identify your non-digits:

from string import *

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

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

In case you want to replace a colon, use quotes " instead of colons '.

Solution 5 - Python

I would not use RegEx for this. It is a lot slower!

Instead let's just use a simple for loop.

TLDR;

This function will get the job done fast...

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

Let's create a very basic benchmark to test a few different methods that have been proposed. I will test three methods...

  1. For loop method (my idea).
  2. List Comprehension method from Jon Clements' answer.
  3. RegEx method from Moradnejad's answer.
# 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)

Now that we have an implementation of each way of removing digits, let's benchmark each one.

Here is some very basic and rudimentary benchmark code. However, it will do the trick and give us a good comparison of how each method performs.

# 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()

Here is the output from the benchmark code.

# 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

As you can see the filter_non_digits_for() funciton is more than four times faster than using RegEx, and about twice as fast as the comprehension method. Sometimes simple is best.

Solution 6 - Python

To extract Integers

Example: sd67637 8 ==> 676378

import re
def extract_int(x):
    return re.sub('[^\d]','', x)

To extract a single float/int number (possible decimal separator)

Example: sd7512.sd23 ==> 7512.23

import re
def extract_single_float(x):
    return re.sub('[^\d|\.]','', x)

To extract multiple float/float numbers

Example: 123.2 xs12.28 4 ==> [123.2, 12.28, 4]

import re
def extract_floats(x):
    return re.findall("\d+\.\d+", x)

Solution 7 - Python

Adding into @MoradneJad . You can use the following code to extract integer values, floats and even signed values.

a = re.findall(r"[-+]?\d*\.\d+|\d+", "Over th44e same pe14.1riod of time, p-0.8rices also rose by 82.8p")

And then you can convert the list items to numeric data type effectively using map.

print(list(map(float, a)))

[44.0, 14.1, -0.8, 82.8]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionObcureView Question on Stackoverflow
Solution 1 - Pythonmar marView Answer on Stackoverflow
Solution 2 - PythonJon ClementsView Answer on Stackoverflow
Solution 3 - PythonInbar RoseView Answer on Stackoverflow
Solution 4 - PythonSaullo G. P. CastroView Answer on Stackoverflow
Solution 5 - PythonDaniel MorellView Answer on Stackoverflow
Solution 6 - PythonMoradnejadView Answer on Stackoverflow
Solution 7 - PythonKiprono Elijah KoechView Answer on Stackoverflow