如何构建动态增长的嵌套列表理解?

2024-10-03 00:26:01 发布

您现在位置:Python中文网/ 问答频道 /正文

假设有以下代码检查一个数的相乘位数是否等于输入数:

results = [a for a in range(10) if a == input]
results += [a*b for a in range(10) for b in range(10) if a*b == input]
results += [a*b*c for a in range(10) for b in range(10) for c in range(10) if a*b*c == input]
...

我希望它能够改变,以便在没有找到结果的情况下继续动态地搜索匹配项。所以:

  • 如果结果是两位数,就不要用一位数继续
  • 如果两位数不能产生结果,请继续使用三位数
  • 等等。。。在

我想用一种优雅的方式来做这件事,即使是一条线,如果不是太渐开线的话。如果根本没有匹配,我还需要一个中断条件来避免无限循环。例如,如果输入的是质数>;10,则没有结果。中断条件应类似于:

^{pr2}$

其中countOfDigits是嵌套列表理解中当前检查的位数。换句话说,我的初始示例的第一行表示countOfDigits == 1,第二行countOfDigits == 2,第三行{}。在


Tags: 代码inforinputif方式情况动态
3条回答

我不认为你想要一个列表理解。我认为发电机在这里会更好:

def generate(x):
    for digits in itertools.count(1):
        for i in itertools.product(range(1, 10), repeat=digits):
            if reduce(operator.mul, i) == x:
                yield i
    if (math.pow(2, digits) > x):
        break

然后你做for i in generate(input_number)。在

(顶部还需要import itertoolsfrom functools import reduce和{})。在

在((数学.pow(2,数字)>;x)只是中断条件。)

编辑:

你想要的是一个可以反复迭代的东西,但它直到尽可能晚才起作用。这不是一个列表,所以列表理解是错误的工具。幸运的是,您可以使用生成器表达式。您的代码非常复杂,因此我们可能希望使用标准库中定义的一些helper,在itertools中。在

让我们从零件的一般情况开始:

[n

   for x0 in range(10) 
   for x1 in range(10)
   ...
   for xn in range(10) 

 if x0 * x1 * ... * xn == input]

我们有三个部分要概括。我们将从嵌套的for循环开始,作为N的参数。为此,我们将使用itertools.product,它接受一个序列序列,类似于[range(10), range(10), ... , range(10)],并从这些序列中产生所有可能的项组合。在多次循环一个序列的特殊情况下,您可以将嵌套深度作为repeat传递,这样我们就可以得到:

^{pr2}$

对于输出中的和,我们可以用sum()将其展平为一个值,对于乘积,实际上没有等效值。我们可以用reduce和一个将两个数字相乘的函数,我们可以从另一个标准库中得到这个函数:operator.mul

^{3}$

我们只需要把这个序列的一个很好的序列变成一个连续的序列

itertools.chain.from_iterable(
     (n
      for x in itertools.product(xrange(10), repeat=n)
      if reduce(operator.mul, x, 1) == input)
     for n in itertools.count(1)
     if 2 ** n > input))
In [32]: input = 32

In [33]: next(itertools.chain.from_iterable(
        (n
         for x in itertools.product(xrange(10), repeat=n)
         if reduce(operator.mul, x, 1) == input)
        for n in itertools.count(1) if 2 ** n > input))
Out[33]: 6

哦,接着说:

next(
    sum(x) 
    for i in range(1, input) # overkill
    for x in itertools.product(range(10), repeat = i) 
    if reduce(operator.mul, x) == input
)

编辑:您已经将问题改为返回乘积而不是求和,因此请将input替换为sum(x)。在

我不能马上确定你是想要第一个匹配,还是你想要所有因子数等于最小的匹配。如果是后者,您可以通过从这个迭代器中取出input, i来完成,然后使用itertools.groupby根据元组中的第二个值收集它们,然后只获取结果中的第一个值,然后对其进行迭代以获得所有匹配项(尽管,因为现在输出的是input,所以除了长度之外,这有点没意思)。在

相关问题 更多 >