Python 加速字符串拆分和连接
我想解决这个问题 数字197被称为循环素数,因为数字197、971和719的所有旋转本身都是素数 一百万以下有多少个循环素数 这是我的解决方案:Python 加速字符串拆分和连接,python,primes,Python,Primes,我想解决这个问题 数字197被称为循环素数,因为数字197、971和719的所有旋转本身都是素数 一百万以下有多少个循环素数 这是我的解决方案: import numpy as np def problem(n=100): circulars = np.array([], np.int32) p = np.array(sieveOfAtkin(n), np.int32) for prime in p: prime_str = str(prime)
import numpy as np
def problem(n=100):
circulars = np.array([], np.int32)
p = np.array(sieveOfAtkin(n), np.int32)
for prime in p:
prime_str = str(prime)
is_circular = True
for i in xrange(len(prime_str)):
m = int(prime_str[i:]+prime_str[:i])
if not m in p:
is_circular = False
if is_circular:
circulars = np.append(circulars, [prime])
return len(circulars)
不幸的是,for循环非常慢!有没有办法加快速度?
我怀疑字符串连接是瓶颈,但我不完全确定!:)强>
有什么想法吗?:)
在这里,我将循环测试隔离到一个函数中,以允许使用列表理解构建列表。把它放在函数中,一旦我们知道它不是循环的,就让它返回
False
。另一种选择是在for
循环中执行,当我们知道它不是循环的时候,则在break
中执行。然后附加到循环的else
子句中的列表中。但是,一般来说,列表比较快于在循环中追加。这里可能不是这样,因为它确实增加了函数调用开销。如果你真的关心速度,那么这两种选择都值得一试
primes = set(primes_to_one_million_however_you_want_to_get_them)
def is_circular(prime, primes=primes):
prime_str = str(prime)
# With thanks to Sven Marnach's comments
return all(int(prime_str[i:]+prime_str[:i]) in primes
for i in xrange(len(prime_str)))
circular_primes = [p for p in primes if is_circular(p)]
我还使用了将全局变量作为默认参数传递给is\u circular
函数的技巧。这意味着它可以作为局部变量而不是更快的全局变量在函数中访问
这里有一种方法,可以在循环中使用else
子句对其进行编码,以消除丑陋的标志并提高效率
circular = []
for p in primes:
prime_str = str(prime)
for i in xrange(len(prime_str)):
if int(prime_str[i:]+prime_str[:i]) not in primes:
break
else:
circular.append(p)
@弧度X。阅读哈希表。答案是集合是使用哈希表实现的。这允许进行O(1)成员资格测试。对于列表或数组,成员资格测试涉及在每个元素上循环,直到找到匹配项。在最坏的情况下,如果找不到匹配项,则必须查看每个元素,使其为O(n)。@aaron:太棒了!非常感谢你!今天我确实学到了一些有用的东西:)最后四行的
是循环的()
可以重写为返回所有的(int(prime_str[I:+prime_str[:I]),在x范围内的I(len(prime_str))
。这应该更快。@Sven捕捉得好。请参阅我的编辑。这样做,可以让您完全摆脱函数调用开销。哦,还有一句话-xrange
可能从1开始,因为我们已经知道p
是素数。为什么要使用字符串?不要对循环使用NumPy数组
——它有固定的大小,每次调用NumPy.append()
,都需要重新分配它。在这里,Python列表是更好的选择。(删除numpy标记,因为问题和当前答案都与numpy无关。)