范围(n)和布尔列表的解释,一一映射,更简单?
#!/usr/bin/python
#
# Description: bitwise factorization and then trying to find
# an elegant way to print numbers
# Source: http://forums.xkcd.com/viewtopic.php?f=11&t=61300#p2195422
# bug with large numbers such as 99, but main point in simplifying it
#
def primes(n):
# all even numbers greater than 2 are not prime.
s = [False]*2 + [True]*2 + [False,True]*((n-4)//2) + [False]*(n%2)
i = 3;
while i*i < n:
# get rid of ** and skip even numbers.
s[i*i : n : i*2] = [False]*(1+(n-i*i)//(i*2))
i += 2
# skip non-primes
while not s[i]: i += 2
return s
# TRIAL: can you find a simpler way to print them?
# feeling the overuse of assignments but cannot see a way to get it simpler
#
p = 49
boolPrimes = primes(p)
numbs = range(len(boolPrimes))
mydict = dict(zip(numbs, boolPrimes))
print([numb for numb in numbs if mydict[numb]])
a=[True, False, True]
b=[1,2,3]
b_a # any such simple way to get it evaluated to [1,3]
# above a crude way to do it in TRIAL
我在寻找的东西是,你能把 TRIAL
简化到下面这种极致的简单吗?有没有什么方法可以做到?
3 个回答
0
在这里创建一个字典其实不是你想要的,因为字典是无序的。把成对的元素保持成对实际上可以简化逻辑,因为你可以遍历这些成对的元素,给这两个元素起个名字,然后在理解代码时使用这些名字。
在Python中,把一个列表和一个对应的索引列表“压缩”在一起的好方法是使用 enumerate
。
所以:
print ([x for (x, y) in enumerate(primes(49)) if y])
0
你可以使用 enumerate
这个函数,配合列表推导式,来大大简化你的代码,变得更简单明了,像这样:
p = 49
print([num for num, isprime in enumerate(primes(p)) if isprime])
2
对于Python 2.7及以上版本,你可以使用 itertools.compress 这个工具。
itertools.compress(b,a)
比如说:
>>> from itertools import compress
>>> a=[True, False, True]
>>> b=[1,2,3]
>>> list(compress(b,a))
[1, 3]
如果不想用那个工具,你也可以用列表推导式来实现。
>>> [j for i,j in zip(a,b) if i]
[1, 3]
如果你想在你的质数列表上进行这个操作,使用enumerate可能会更简单。
>>> primes = [False, False, True, True, False, True]
>>> list(compress(*zip(*enumerate(primes))))
[2, 3, 5]