【问题标题】:Find prime numbers with list comprehension使用列表理解查找素数
【发布时间】:2020-12-05 07:22:52
【问题描述】:

我正在尝试编写代码来选择列表中的素数。用户给出一个极限,程序显示从 2 到极限的所有素数。我试图尽可能减少行数,但对一些我无法理解的情况感到惊讶。如果您能帮助我,我将不胜感激。

我写了这段代码:

# returns all integers from 2 to a limit given by the user. 

def primes(limit):
    # generates the numbers. 
    lista = range(2, limit + 1)
    
    p = 2
    
    while p < limit:
        #filters the prime numbers and places in a list.
        lista = [i for i in lista if i == p or i % p != 0]
    
        p += 1
    

    return lista

        
def main():
    #asks the user for the limit number.
    l = int(input("Enter the limit: "))
    
    #call the function which selects the numbers and returns the result. 
    return print(primes(l))

#Ensures that the main program only runs when the functions have not been imported into another file.
if __name__ == '__main__':
    main()

它按我的预期运行,但是当我尝试删除第一个列表分配行并将范围函数直接包含到理解中时,它不起作用。为什么?

# returns all integers from 2 to a limit given by the user. 

def primes(limit):
    p = 2
    
    while p < limit:
        #filters the prime numbers and places in a list.
        lista = [i for i in range(2, limit + 1) if i == p or i % p != 0]
    #or lista = [i for i in range(2, limit + 1) if i == p or i % p != 0]
    #or lista = [i for i in [*range(2, limit + 1)] if i == p or i % p != 0]
    
        p += 1
    

    return lista

        
def main():
    #asks the user for the limit number.
    l = int(input("Enter the limit: "))
    
    #call the function which selects the numbers and returns the result. 
    return print(primes(l))

#Ensures that the main program only runs when the functions have not been imported into another file.
if __name__ == '__main__':
    main()

其他问题。由于 range 行不是列表,我修复它只是为了改进代码,但是当我将值的名称从“lista”更改为另一个名称时,我发现它也不起作用。为什么?

# returns all integers from 2 to a limit given by the user. 

def primes(limit):
    # generates the numbers. 
    nums = range(2, limit + 1)

    p = 2
    
    while p < limit:
        #filters the prime numbers and places in a list.
        lista = [i for i in nums if i == p or i % p != 0]
    
        p += 1
    

    return lista

        
def main():
    #asks the user for the limit number.
    l = int(input("Enter the limit: "))
    
    #call the function which selects the numbers and returns the result. 
    return print(primes(l))

#ensures that the main program only runs when the functions have not been imported into another file.
if __name__ == '__main__':
    main()

感谢您的关注。

【问题讨论】:

  • 因为你在while p &lt; limit循环中修改了lista,所以每次运行循环的启动顺序都不一样。当您将lista 更改为range(2, limit + 1)nums 时,您将开始序列更改为一个常量值,您的代码将只过滤掉最后一个p 值的倍数。

标签: python list range list-comprehension


【解决方案1】:

这种单线效果很好:

def primes(val):
    return [x for x in range(2, val) if all(x % y != 0 for y in range(2, x))]

print(primes(10))

【讨论】:

  • 伊朗你为什么不接受这个答案呢?
  • 当然可以,但效率极低。
【解决方案2】:

感谢您的关注。我喜欢我们的朋友 Yash Makan 的回答,但是当我尝试更大的数字时,例如 100000,它从来没有让我得到结果(或者我没有耐心等待)。所以我继续思考这个问题并得到以下是计算这个问题的最快方法,我可以通过列表理解实现。请注意计算数百万个数字的速度。

# returns all integers from 2 to a limit given by the user. 

def primes(limit):
    
    l = [i for i in range(2, limit + 1) if all(i % j != 0 for j in [2, 3, 5])]    
    lista = []
    return [2, 3, 5] + [lista.append(i) or i for i in l if all( i % j != 0 for j in lista[:int((len(lista) ** .5) + 1)])]

        
def main():
    l = int(input("Enter the limit: "))
    
    return print(primes(l))

if __name__ == '__main__':
    main()

【讨论】:

  • 如果你想快两倍,请将range(2, int(i**.5) + 1) 替换为itertools.chain([2], range(3, int(i**.5) + 1, 2)。当然,这仍然没有埃拉托色尼筛法快。
  • 我尝试了埃拉托色尼筛法,但对于非常大的数字,它并不是那么好。
  • “不太好”是什么意思?还有其他方法可以生成素数列表,但 Sieve 是简单性和效率之间的良好折衷。
  • 对于非常大的数字不太好,因为它不是那么快。我无法将它写在列表理解中,也无法找到更快的方法来做到这一点。但是,如果您知道一种通过列表理解来编写埃拉托色尼筛法的方法,我将非常感激。
  • 有很多关于如何编写好的筛子的帖子,我熟悉的一个是stackoverflow.com/q/9301781/5987。我认为 just 列表理解是不可能的,但如果你搜索你可能会找到一个。
猜你喜欢
  • 1970-01-01
  • 2011-08-30
  • 1970-01-01
  • 2011-11-08
  • 1970-01-01
  • 2014-07-18
  • 2018-08-13
  • 1970-01-01
相关资源
最近更新 更多