更快速地检查字符串中的所有数字

时间:2018-01-27 10:38:44

标签: python python-3.x

我有一个包含数字的字符串。我想检查字符串是否包含0-9之间的所有数字。目前,我检查的方式非常慢,对于大字符串肯定没用。以下是我的代码:

import sys

# check if all numbers (0-9) exist in a string
num = "31586055033755830765"
for i in num:
    if int(i) not in [0, 1, 2 ,3 ,4 ,5 ,6, 7, 8, 9]:
        print("The string doesn't have all the numbers")
        sys.exit(1)

代码工作正常,但速度很慢。有没有更快的方法来完成任务?

6 个答案:

答案 0 :(得分:7)

您的代码性能不佳的几个原因:

  • 每次迭代都会创建一个新列表([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  • 列表上的
  • in非常昂贵(O(n))。而不是in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]更喜欢in {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}。集合上的in要便宜得多(O(1))。
  • 它将num中的每个字符转换为整数(函数调用+转换本身所用的时间)。相反,您可以将数字比较为字符串:

    if i not in {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
    

这些更改将提高代码的性能,但您只需使用集合即可使用完全不同,更短,更快的方法:

import string

num = '31586055033755830765'

print(set(num) == set(string.digits))
# False

print(set('1234567890') == set(string.digits))
# True

答案 1 :(得分:2)

我就是这样做的:

def check_num(num):
    not_found="0123456789"
    for i in num:
        if i in not_found:
            not_found = not_found.replace(i, '')
            if not not_found:
                break
    return not_found

运行

num = "31586055033755830765"

print(bool(not check_num(num))) # False

此代码一次检查一个数字,如果找到所有数字,则退出循环。

运行时间的大小为the other answer

import string
import random
num=str(random.getrandbits(256))

In [35]: %timeit set(num) == set(string.digits)
100000 loops, best of 3: 9.89 µs per loop

In [36]: %timeit bool(not check_num(num))
100000 loops, best of 3: 14.9 µs per loop

对于平均情况下的非常大的数字(当数字包含均匀分布的数字时)它稍微好一些

In [47]: num=str(random.getrandbits(2048))

In [48]: %timeit bool(not check_num(num))
100000 loops, best of 3: 15.8 µs per loop

In [49]: %timeit set(num) == set(string.digits)
10000 loops, best of 3: 37.2 µs per loop

答案 2 :(得分:1)

您也可以在此处使用all()

>>> from string import digits
>>> numbers = set(digits)
>>> num = '31586055033755830765'
>>> all(x in numbers for x in num)
True

答案 3 :(得分:0)

您可以使用散列。假设你的字符串只有数字

num = "31586055033755830765"
temp = dict()
for i in num:
    if not i in a:
       a[i] = True
if (len(a)!=10):
    sys.exit(1)

答案 4 :(得分:0)

如果您的字符串还包含与数字不同的字符串,则为

import string

num = 'abc0123456789'

print(set(num) == set(string.digits))
# False

all_numbers = set(string.digits)
found = False
for n in num:
    all_numbers.discard(n)
    if not all_numbers:
        found = True
        break
print(found)
# True

答案 5 :(得分:-1)

你可以试试这个:

test='1234567890'
print(any(list(filter(lambda x:x not in "31586055033755830765" ,test))))

如果result为True,则表示所有int都不在秒中,如果result为false,则表示所有int都在字符串中。

输出:

True

因为

['2', '4', '9'] are not in "31586055033755830765"