Python Forum
How to exclude characters when counting digits - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Homework (https://python-forum.io/forum-9.html)
+--- Thread: How to exclude characters when counting digits (/thread-11289.html)

Pages: 1 2


RE: How to exclude characters when counting digits - buran - Jul-03-2018

(Jul-03-2018, 11:27 AM)gruntfutuk Wrote: I didn't run time it.
import timeit
import string

my_string = 'DS80A98SD09a8SD098ASD098A09sd8c0a9SCNAfsdg8fbvdfad098098f00A'*1000

def count_func(s):
    return sum(c.isdigit() for c in s)


def smart_count_digits(my_string):
    orig_length = len(my_string)
    for digit in string.digits:
        my_string = my_string.replace(digit, '')
    return orig_length - len(my_string)

elapsed = timeit.timeit('count_func(my_string)', number=1000, setup='from __main__ import count_func, my_string')
print( 'count_func took {:.3f} sec'.format(elapsed))

elapsed = timeit.timeit('smart_count_digits(my_string)', number=1000, setup='from __main__ import smart_count_digits, my_string')
print('smart_count_digits took {:.3f} sec'.format(elapsed))
Output:
count_func took 15.112 sec smart_count_digits took 1.181 sec



RE: How to exclude characters when counting digits - gruntfutuk - Jul-03-2018

(Jul-03-2018, 11:59 AM)buran Wrote:
Output:
count_func took 15.112 sec smart_count_digits took 1.181 sec

Brilliant. Thanks for the timings. I expect my original was probably also faster. I'm going to have to start timing things more often.


RE: How to exclude characters when counting digits - ichabod801 - Jul-03-2018

def ick_count(text):
    return len(text) - sum([text.count(digit) for digit in string.digits])
Output:
count_func took 6.773 sec smart_count_digits took 0.908 sec ick_count took 0.550 sec



RE: How to exclude characters when counting digits - DeaD_EyE - Jul-03-2018

(Jul-03-2018, 11:27 AM)gruntfutuk Wrote:
def count_func(s):
    return sum(c.isdigit() for c in s)
would be pretty efficient, but I didn't run time it.

I like this solution also, but I can't test it.
My CPU Speed is not fixed, so I get not usable results.

I guess the methodcall isdigit() takes bit time.
Maybe this can be faster:

import string


def count_func(s):
    return sum(1 for c in s if c in set(string.digits))
But again, I can't benchmark it :-/


RE: How to exclude characters when counting digits - ichabod801 - Jul-03-2018

digit_re = re.compile('\d+')

def re_count(text):
    return len(text) - len(digit_re.sub(text, ''))
Output:
count_func took 7.043 sec smart_count_digits took 0.945 sec ick_count took 0.622 sec re_count took 0.061 sec
Edit: Function gave wrong answer, corrected function and reran times.


RE: How to exclude characters when counting digits - ichabod801 - Jul-03-2018

On further examination, both my functions are giving the wrong answer, so they shouldn't be considered.


RE: How to exclude characters when counting digits - buran - Jul-03-2018

(Jul-03-2018, 01:29 PM)ichabod801 Wrote: On further examination, both my functions are giving the wrong answer, so they shouldn't be considered.

I'm on comute, so would you timeit this one
def ick_count(text):
    return sum(text.count(digit) for digit in string.digits)



RE: How to exclude characters when counting digits - gruntfutuk - Jul-03-2018

On my iPad:
print('smart:',timeit.timeit("smart_count_digits(my_string)", setup = "from __main__ import smart_count_digits, my_string", number = 1000))
print('count:',timeit.timeit("count_digits(my_string)", setup = "from __main__ import count_digits, my_string", number = 1000))
print('ick:',timeit.timeit("ick_count(my_string)", setup = "from __main__ import ick_count, my_string", number = 1000))
Output:
smart: 1.1727769580029417 count: 8.195804083981784 ick: 0.5881457919895183
ick_count is the winner.


RE: How to exclude characters when counting digits - volcano63 - Jul-03-2018

After a lecture recently delivered in another forum about the evilness of the non-functional ways Hand , I started playing around with map, filter and reduce (I was using them occasionally before, but I decided to raise my level of involvement)

So, adding map to @ichabod801's solution should have brought salvation Pray ? Apparently not Confused

Output:
In [4]: def ick_count(text): ...: return sum(text.count(digit) for digit in string.digits) ...: ...: def ick_map_count(text): ...: return sum(map(text.count, string.digits)) ...: ...: In [5]: %timeit ick_count(my_string) 423 µs ± 6.69 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) In [6]: %timeit ick_map_count(my_string) 423 µs ± 10.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)



RE: How to exclude characters when counting digits - volcano63 - Jul-03-2018

(Jul-03-2018, 01:13 PM)DeaD_EyE Wrote:
import string
def count_func(s):
    return sum(1 for c in s if c in set(string.digits))

It may be re-written as
def count_func(s):
    return sum(c in set(string.digits) for c in s)
You can add booleans as integers.

Still, major loser to @ichabod801
Output:
In [8]: %timeit dead_eye_count_func(my_string) 31.8 ms ± 1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) In [9]: %timeit ick_count(my_string) 467 µs ± 12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
With a little tweak - making set of digits "static"
Output:
In [12]: def frozen_set_count_func(s, _digits=frozenset(string.digits)): ...: return sum(c in _digits for c in s) ...: In [13]: %timeit frozen_set_count_func(my_string) 5.7 ms ± 264 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)