Count unique digits one liner (efficiently)

前端 未结 3 1203
春和景丽
春和景丽 2020-12-12 05:51

I\'m searching for a way to count unique digits efficiently with a one liner.

For example: given the integer 623562, return value would be 4

相关标签:
3条回答
  • I'm having a hard time believing that len(set(str(num))) isn't fast enough for you. Here is a test that does len(set(str())) of a random, very large number 100,000 times:

    % python -m timeit -s 'import random' 'for i in range(100000): \
      len(set(str(random.randint(199123212312399956789, 1000000099999999123091230000000))))'
    10 loops, best of 3: 456 msec per loop
    

    And a decent chunk of that time is just generating the random numbers! If you really need to go faster than that, I'd think you should consider an alternative language.

    0 讨论(0)
  • 2020-12-12 06:14

    sets are optimized for this creation. Unless you want to roll out your own decimal-to-string conversion (and that would take more than one line), it's the way to go.

    range only allocates memory in Python 2.x. For small numbers like 623562, the memory shouldn't be a problem. For larger numbers, use xrange in Python 2.x or simply switch to Python 3.x, where range generates the numbers just in time.

    0 讨论(0)
  • 2020-12-12 06:14

    Here's a way that avoids creating a set each time. All but the last line are initialisation code so only happen once:

    >>> from operator import or_
    >>> from collections import Counter
    >>> from functools import reduce
    >>> bits = {str(i):2**i for i in range(10)}
    >>> counts = [Counter(format(i,'b'))['1'] for i in range(2**10)]
    
    >>> counts[reduce(or_, (bits[c] for c in str(623562)))]
    4
    

    However, it is about 3 times slower than the simple, clear, obvious len(set(str(i))). As usual in Python making things more complicated or trying to be excessively clever will come back and bite you on performance.

    0 讨论(0)
提交回复
热议问题