例如,仅将 itertools 与元组 (2,3,4) 一起使用的想法:
有多个笛卡尔积:
(2,),(3,),(4,) # repeat 1
(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2), (4, 3), (4, 4) # repeat 2
...
对于每个元组,使用 reduce 和 operator.mul 和起始值 1,将它们相乘:
reduce(operator.mul, tuple, 1)
这将产生 2 级笛卡尔积的乘法:
[reduce(operator.mul,t,3) for t in itertools.product((1,2,3),repeat=2)]
>>>[3, 6, 9, 6, 12, 18, 9, 18, 27]
现在,我们需要增加repeat 直到满足停止条件,例如:每次乘法都会产生大于top 的结果。由于计数的最小值是2(因为1 乘以1 很多次只是1,所以它不会计数)我们可以将x 乘以2 而低于top。所以:top/2 = x,意味着我们可以遍历range(1,top/2):
[reduce(operator.mul,t,1) for c in range(1,10/2) for t in itertools.product((1,2,3),repeat=2) if reduce(operator.mul, t, 1) < 10]
这会产生重复的值,所以让我们将它们转换成一个集合:
set([reduce(operator.mul,t,1) for c in range(1,10/2) for t in itertools.product((1,2,3),repeat=2) if reduce(operator.mul, t, 1) < 10])
仅使用itertools 可能会很麻烦,但解决方案似乎很漂亮。我确信可以通过引入更好的停止条件来优化它。最终代码如下所示:
注意:有一个素数定理可以让您将停止条件优化为math.sqrt(top)
import math
def f(t,m):
return set([reduce(operator.mul, t1, 1) for c in range(1,int(math.sqrt(m)) for t1 in itertools.product(t,repeat=c) if reduce(operator.mul,t1,1) < m])
f((2,3,4),10)
>>>set([2, 3, 4, 6, 8, 9])
希望这能给你另一个想法:)