简体   繁体   English

使用列表推导生成素数列表

[英]Generating a list of prime numbers using list comprehension

I'm trying to create a list of all the prime numbers less than or equal to a given number. 我正在尝试创建所有小于或等于给定数字的质数的列表。 I did that successfully using for loops. 我使用for循环成功做到了这一点。 I was trying to achieve the same using list comprehension using python. 我试图使用python使用列表理解来实现相同的目的。 But my output has some unexpected values. 但是我的输出有一些意外的值。

Here is my code.. 这是我的代码。

pr=[2]
pr+=[i for i in xrange(3,num+1) if not [x for x in pr if i%x==0]]

where num is the number I had taken as input from user. 其中num是我从用户那里输入的数字。

The output of the above code for 上面代码的输出为

num=20 is this:  [2, 3, 5, 7, 9, 11, 13, 15, 17, 19]

I'm puzzled as to why 9 and 15 are there in the output. 我对为什么输出中有9和15感到困惑。 What am I doing wrong here? 我在这里做错了什么?

It simply doesn't work that way. 这样根本行不通。 List comprehensions are evaluated separately, so you can imagine it like this: 列表推导是单独评估的,因此可以像这样想象:

pr = [2]
tmp = [i for i in xrange(3,num+1) if not [x for x in pr if i%x==0]]
pr += tmp

By the time tmp is evaluated, pr only contains 2 , so you only ever check if a number is divisible by 2 (ie if it's even). 在评估tmppr仅包含2 ,因此您仅检查数字是否可被2整除(即,是否为偶数)。 That's why you get all uneven numbers. 这就是为什么您得到所有​​不平衡数字的原因。

You simply can't solve this nicely using list comprehensions. 你根本解决不了这个很好应用列表解析。


† Not nicely, but ugly and in a very hackish way, by abusing that you can call functions inside a list comprehension: †不好,但是很丑陋,而且很笨拙,通过滥用可以在列表理解内调用函数:

pr = [2]
[pr.append(i) for i in xrange(3,num+1) if not [x for x in pr if i%x==0]]
print(pr) # [2, 3, 5, 7, 11, 13, 17, 19]

This abuses list comprehensions and basically collects a None value for each prime number you add to pr . 此滥用列表理解力,并且基本上为您添加到pr每个素数收集None值。 So it's essentially like your normal for loop except that we unnecessarily collect None values in a list… so you should rather allow yourself to use a line break and just use a normal loop. 因此,除了我们不必要地在列表中收集None值外,它本质上与您的常规for循环类似,因此您应该允许自己使用换行符,而仅使用常规循环。

Your list pr doesn't update until after your entire list comprehension is done. 直到完成整个列表理解后,您的列表pr才会更新。 This means your list only contains 2, so every number dividable by 2 is not in the list (as you can see). 这意味着您的列表仅包含2,因此每个可被2除的数字不在列表中(如您所见)。 You should update the list whenever you found a new prime number. 每当发现新的素数时,都应更新列表。

This is because the pr += [...] is evaluated approximately as this: 这是因为pr += [...]的评估大致如下:

pr = [2]
tmp = [i for i in xrange(3,num+1) if not [x for x in pr if i%x==0]]
pr.extend(tmp) 

So while tmp is generated, contents of pr remains the same ( [2] ). 因此,当生成tmppr内容保持不变( [2] )。

I would go with function like this: 我会使用这样的功能:

>>> import itertools
>>> def primes():
...     results = []
...     for i in itertools.count(2):
...         if all(i%x != 0 for x in results):
...             results.append(i)
...             yield i
...
# And then you can fetch first 10 primes
>>> list(itertools.islice(primes(), 10))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
# Or get primes smaller than X
>>> list(itertools.takewhile(lambda x: x < 50, primes()))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Note, that using all is more efficient than creating array and testing whether it's empty. 请注意,使用all比创建数组和测试数组是否为空更有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM