列表理解没有过滤器

时间:2018-05-12 10:54:53

标签: python python-3.x algorithm list list-comprehension

最近在网上发现了这段代码:

nonprime = [j for i in range(2, 8) for j in range(i*2, 50, i)]

上面的代码似乎在计算50以下的所有非素数,但我没有得到逻辑。 我研究了python中的列表推导,并观察它使用过滤器根据条件进行过滤, 但是我无法理解两个for循环是如何计算这些非素数的。

5 个答案:

答案 0 :(得分:3)

这个列表理解与这两个嵌套for循环的作用相同:

nonprime=[]
for i in range(2,8):
    for j in range(i*2, 50,i):
        nonprime.append(j)

因此在外循环中,i在每次迭代中仅增加1,并且取值i = 2,3,4,5,6,7。 j上的内部for循环取决于外循环。它从2*i开始,j在每次迭代中增加i

因此对于ì=2,内部循环从j=4开始,j采用值j=4,6,8,...,48。 然后ì在外部循环中增加到3,j采用值6,9,12,...48

请注意,nonprime列表不会创建唯一元素,因为例如6会出现多次。

正如Bakuriu正确地指出的那样,这种方法使用了Sieve of Eratosthenes

答案 1 :(得分:2)

循环基本上是Sieve of Erathostenes,但不是删除数字而是保留它们。

在Erathostenes的筛选中,你删除倍数的已知素数"。最有效的方法是,给定一个素数p,删除数字p*p然后p*(p+1)等,直到达到限制并继续下一个素数q ,并开始q*q

列表理解是这个的一个小变化。您可以将i*2替换为i*i,但仍然可以获得相同的数字(尽管重复次数较少)。

在Erathostenes的筛选中,您通常删除除2以外的所有偶数,然后使用2*i作为范围的步骤,因为您只需要考虑奇数的素数。显然,如果你想获得所有非素数,那么这不是真的,以便"优化"不起作用。

答案 2 :(得分:2)

这个答案的关键在于数学:

If a number n>1 is not prime, then it has a prime factor <= sqr(n)

现在我们要解释逻辑。请注意sqrt(50) < 8,这是第一个range的限制。

我们可能会将嵌套列表理解重写为常规循环。我们可以使用set而不是列表,这将包含不必要的重复元素:

res = set()

for i in range(2, 8):
    for j in range(i*2, 50, i):
        res.add(j)

外部循环迭代所有i < sqrt(50)

对于每个i,内部循环迭代所有i的倍数小于50。

通过上述数学陈述,我们得到的所有非素数都在50以下。这是正确的,因为我们正在耗尽所有素因子&lt; = sqrt(50)。

答案 3 :(得分:0)

这是该代码的非列表理解版本:

nonprime = []
for i in range(2, 8):
    for j in range(i*2, 50, i):
        nonprime.append(j)

一步一步:

for i in range(2, 8):

到目前为止,非常简单。这将返回数字2到7,当它到达8时停止。在此循环的第一次迭代中,i = 2

    for j in range(i*2, 50, i):

现在我们正在创建一个内循环。我们将i替换为2,这样我们就可以看到它在外部循环的第一次迭代中所做的事情。

    for j in range(2*2, 50, 2):

    for j in range(4, 50, 2)

这将返回一个以4开头的数字列表,每次加注2(6,8,10),当它达到50时停止。如果你在nonprime查看结果,你可以看到我会看到这些数字。

外循环的下一次迭代i = 3。所以:

    for j in range(i*2, 50, i):

变为:

    for j in range(3*2, 50, 3):

或者:

    for j in range(6, 50, 3):

从6开始,我们继续添加3并在到达50时停止。您会在nonprime

中显示的值列表中看到此序列

这就是所有这些代码正在做的事情。正如@Bakuriu所指出的那样,这基本上是Sieve of Erathostenes,但这是另一个主题。

答案 4 :(得分:0)

它基本上计算范围(2,8)低于50的所有值的倍数。它将包含重复的值。

# iterates over values in this range [2, 7]
for i in range(2, 8)

# iterates over multiples of i lower than 50
for j in range(i*2, 50, i)

结果如下:

[ 4, 6, 8, ... # multiples of 2 lower than 50
 6, 9, 12, ... # multiples of 3 lower than 50
(...)
14, 21, 28, ... # multiples of 7 lower than 50
]