列表理解与多项任务

list comprehension with multiple assignments

我现在有这个用于分解大数的代码:

def f1(n):
    return [[i, n//i] for i in range(1 , int(n**0.5) + 1) if n % i == 0]

这是迄今为止我见过的最快的版本(如果有更快的方法我也很想知道),但我想要一个没有嵌套的所有因素的列表(所以我想要类似的东西:[factor 1, factor 2, factor 3,..., factor n-3, factor n-2, factor n-1, factor n] 等等。顺序并不重要。

因此我想知道是否有一种方法可以通过列表理解来归因于多个分配。

def f1(n):
    return [i, n//i for i in range(1 , int(n**0.5) + 1) if n % i == 0]

这样我就没有嵌套列表了。它会更快,速度至关重要。

我查看了文档,但找不到多个分配的单个示例。

您可以使用 sum() 获得所需的结果。例如:

>>> sum([[1,6],[2,3]],[])
[1, 6, 2, 3]

我们可以根据您现有的代码定义答案:

def f2(n):
    return sum(f1(n), [])

但是,请注意当 n 是一个完全平方时,您的代码 returns 平方根两次:

>>> f1(9)
[[1, 9], [3, 3]]
>>> f2(9)
[1, 9, 3, 3]

使用itertools.chain

from itertools import chain

def f1(n):
    return list(chain.from_iterable([i, n//i] for i in xrange(1 , int(n**0.5) + 1) if not n % i))

如果您不需要列表,请删除链上的列表调用,然后迭代返回的链对象。

如果优化很重要,您应该使用扩展和 xrange:

def f1(n):
    l = []
    for i in xrange(1, int(n**0.5)+1):
        if not n % i:
            l.extend((i,n//i))
    return l

列表推导式很好,但有时它们并不是最佳解决方案,具体取决于对可读性和速度的要求。有时,只写出隐含的 for 循环(和 if 语句)更具可读性和更快。

def factors(n):
    l = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            l.append(i)
            l.append(n//i)
    return l

对于小数字,上述函数比列表理解更快。在更大的数字(1,000,000 和更大)下,函数和列表理解在速度方面是相等的。

为了稍微提高速度,您还可以缓存列表的附加方法,尽管这会使函数的可读性稍差。

def factors(n):
    l = []
    append = l.append
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            append(i)
            append(n//i)
    return l

速度比较:

In [86]: %timeit factors_list_comprehension(1000)
100000 loops, best of 3: 7.57 µs per loop

In [87]: %timeit factors_function(1000)
100000 loops, best of 3: 6.24 µs per loop

In [88]: %timeit factors_optimised_function(1000)
100000 loops, best of 3: 5.81 µs per loop

In [89]: %timeit factors_list_comprehension(1000000)
10000 loops, best of 3: 111 µs per loop

In [90]: %timeit factors_function(1000000)
10000 loops, best of 3: 108 µs per loop

In [91]: %timeit factors_optimised_function(1000000)
10000 loops, best of 3: 106 µs per loop