[英]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). 在评估tmp
, pr
仅包含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]
). 因此,当生成tmp
, pr
内容保持不变( [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.