Python 3:超过 100 个索引的列表在索引 47 之后循环。为啥?我该如何阻止这个?

Posted

技术标签:

【中文标题】Python 3:超过 100 个索引的列表在索引 47 之后循环。为啥?我该如何阻止这个?【英文标题】:Python 3: List of over 100 indices cycles back around after index 47. why? how do I stop this?Python 3:超过 100 个索引的列表在索引 47 之后循环。为什么?我该如何阻止这个? 【发布时间】:2017-05-13 04:29:36 【问题描述】:

所以这是一个获取第 n 个素数的函数。我知道它以前做过,而且我的方法可能不是很有效(新编码器顺便说一下过去的小涉足)。 无论如何,下面的代码工作并返回所提供索引的素数。 即:

ind = 4
final[1,2,3,5,7,11]
return final[ind-1]
returns: 5

但是 final[51-1] 返回 final[3-1] 中的内容。似乎在索引 47 之后它会循环回来并重新开始。我已经打印了包含在最终列表中的整个列表。它会打印每个素数,甚至是那些超过 47 的素数。我不确定发生了什么。 python中的列表有限制吗?

代码如下:

def nthPrime(ind): #gets nth prime number. IE: 5th prime == 11. works based off very in-efficient version of Sieve of Eratosthenes. but in increments of 200
    p = 
    T = 2
    incST = 2
    incEND = incST + 200
    final=[1]

    while len(final) < ind:
        for i in range(incST,incEND):
            p[i] = True

        while T <= math.sqrt(incEND):
            l = 0
            while l <= incEND:
                p[T**2 + (T*l)] = False
                l+=1
                if T**2+(T*l) > incEND:
                   break

            for k,v in p.items():
                if p[k] == True and k > T:
                    T = int(k)
                    break

        for k in p:
            if p[k] == True:
                final.append(k)

        incST = incEND + 1
        incEND = incST + 200

    '''
    currently function works perfectly for
    any index under 48.
    at index 48 and above it seems to start
    back at index 1.
    IE: final[51]
    ^would actually return final[4]
    '''


    return final[ind-1]

【问题讨论】:

如果您尝试用语言(尽可能简短地)解释您的方法是什么,以及您是如何尝试实现它的,那么错误可能会很快被发现。 您可以随时在 www.pythontutor.com 上可视化您的 Python 代码,以找出问题所在。 【参考方案1】:

这不是 Python 问题,问题在于您如何计算结果。当您执行final[51] 时,它实际上会返回持有该位置的值,请​​执行以下操作:

# Modify your line
# return final[ind-1]
# return final

# Call your method
o_final = nthPrime(100)
for k in range(len(o_final)):
    print(k, y[k])

然后你意识到在 pos 93 你到达下一个并继续递增。

【讨论】:

这似乎是它应该做的。 nthPrime(4) 应该只返回第 4 个素数,而不是前 4 个素数。【参考方案2】:

您需要计算列表中有多少个素数,但是您在循环中累积了final,因此您在循环中将所有数字加到了限制数次。在 199 之后再次从 2 开始。

另外,使用字典和依赖顺序是危险的。您应该在迭代时对它们进行排序。

我的解决方案只计算素数以知道何时结束循环,并在最后组成列表,省略 1 并将索引移动 1。

我在迭代字典时也会对字典进行排序,以确保:

import math

def nthPrime(ind): #gets nth prime number. IE: 5th prime == 11. works based off very in-efficient version of Sieve of Eratosthenes. but in increments of 200
    p = 
    T = 2
    incST = 2
    incEND = incST + 200

    lenfinal = 1
    while lenfinal < ind:
        for i in range(incST,incEND):
            p[i] = True

        while T <= math.sqrt(incEND):
            l = 0
            while l <= incEND:
                p[T**2 + (T*l)] = False
                l+=1
                if T**2+(T*l) > incEND:
                   break

            for k,v in sorted(p.items()):
                if v and k > T:
                    T = int(k)
                    break


        incST = incEND + 1
        incEND = incST + 200
        # compute length, no need to order or to actually create the list
        lenfinal = sum(1 for k,v in p.items() if v)

    # now compose the list
    final = [k for k,v in sorted(p.items()) if v]

    return final[ind-2]

【讨论】:

哇。很棒的反应。 哇。很棒的回应。我从中学到了很多。不仅仅是我做错了什么。但我也不知道您不必明确说明 v== True。也不知道您可以在创建列表中执行 if 语句。谢谢。这行得通。 是的,几乎是codereview.stackexchange.com 的候选人。我不确定(我确定相反)生成整个列表以获取一个 1 元素是否未优化。嗯,它有效。我不会选择字典而是选择list,以避免不必要的散列。 是的,我正在挑战。关键是效率。我知道我与此相去甚远。这是我第一次尝试这个特殊的挑战。最终结果需要能够快速得到第 n 个素数,其中 n=200000。当我在 IDLE 中运行此代码并将其传递 200000 作为要获取的索引时,它就坐在那里。所以......是的......将不得不再试一次。 一旦成功,不要犹豫,将工作代码发布到codereview.stackexchange.com 并请求帮助。寻求更好的性能也是这里的主题。你也可以在那里找到我:)【参考方案3】:

一个更有效的方法是递归函数: 我会在代码中做一些解释。

def nthPrime(ind):
    first_prime=1                              #first prime number
    number = 1                                 # all numbers that we will check, this will be incremented
    prime_numbers = [first_prime]              # The list of prime numbers we will find

    def findPrimeInPosition(ind, number):
        if ind > len(prime_numbers):           # This recursive function will exit if find a sufficient number of primes
            number+=1                          # incrementing to check the next number
            is_prime = True                    # Assuming number is a prime

            for p in prime_numbers[1:]:        # Check if it is a prime
                if not number % p:
                    is_prime = False

            if is_prime:
                prime_numbers.append(number)   # Add to the list of primes

            findPrimeInPosition(ind, number) 
        return prime_numbers[-1]               # Get the last element found
    return findPrimeInPosition(ind, number)

使用示例:

print nthPrime(47)
>> 199
print nthPrime(48)
>> 211

【讨论】:

这看起来确实更整洁。我现在在玩它。谢谢。我会看看我是否可以发布我的原始和你的时间比较。 所以...在较低的索引下它似乎确实稍快一些。不过,我无法测试出更高的指数。 Python 开始抛出 ind = 2000 的错误: RecursionError: maximum recursion depth exceeded in comparison 这需要能够处理 LARGE 数字。至少到第 200,000 个索引。 所以我将递归函数更改为 while 循环。您的代码将时间几乎缩短了一半。 >>> OP.nthPrime(47) [211, 0.004000425338745117] >>> OP.nthPrime2(47) [211, 0.003000497817993164] >>> OP.nthPrime(2000) [17539, 11.65716552734325] >>0> OP. ) [17389, 6.237623691558838] >>> 太好了,while 循环确实可以完成这项工作。

以上是关于Python 3:超过 100 个索引的列表在索引 47 之后循环。为啥?我该如何阻止这个?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 python 3.4 tkinter“索引错误:列表索引超出范围”中修复此错误

python-列表方法介绍

文章汇总索引与内容简介

Python 简单练习题100道,

如何在 Python 中使用索引列表对 np.array 进行索引

使用唯一索引索引列表