Python:'字符串索引超出范围'

时间:2013-06-18 22:03:04

标签: python

我快速搜索但找不到任何有助于我解决问题的内容。

我正在尝试制作一个程序,该程序需要前5个数字并获取其产品,如果该产品是迄今为止发现的最大数字,则设置为此类。

我的代码是:

string = str(integer)

x = 0
largest = 0
stringlength = len(string)

while x < stringlength:
    a = int(string[x])
    b = int(string[x+1])
    c = int(string[x+2])
    d = int(string[x+3])
    e = int(string[x+4])
    if (a*b*c*d*e > largest):
        largest = a*b*c*d*e
        print(largest)
    x += 1

print(largest)

我排除了整数值本身,但作为参考,它是1000位数。每当我尝试运行此代码时,我得到“IndexError:字符串索引超出范围”。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:7)

string = str(integer)

x = 0
largest = 0
stringlength = len(string)

while x < stringlength-4: # going to -5 would be out of rangue
    a = int(string[x])
    b = int(string[x+1])
    c = int(string[x+2])
    d = int(string[x+3])
    e = int(string[x+4])
    if (a*b*c*d*e > largest):
        largest = a*b*c*d*e
        print(largest)
    x += 1

print(largest)

答案 1 :(得分:2)

这是一个经典的off-by-one error(或者,在这种情况下,是4分之一的错误)。

x到达stringlength-4时,x+4stringlength,已超过string的结尾。因此,您需要x < stringlength-4,而不是x < stringlength

但您可能需要考虑重写代码以使用更高级别的抽象,以使这些问题更难以考虑并更容易思考。


首先,而不是:

x= 0
while x < stringlength:
    # ...
    x += 1

这样做:

for x in range(stringlength):

然后你可以解决这个问题:

for x in range(stringlength-4):

但是让我们更进一步。


如果您对字符串进行切片,则不会得到IndexError

for x in range(len(stringlength)):
    a, b, c, d, e = map(int, string[x:x+4])

但是,现在您将在解包中获得ValueError。但实际上,您无需在此处将5个单独的变量解压缩。只需保留序列并将其乘以。 (你可以用循环来做到这一点,但在我看来,这是少数情况之一reduce是用Python编写内容的最可读方式。)

for x in range(len(stringlength)):
    values = map(int, string[x:x+4])
    prod = reduce(operator.mul, values)
    if prod > largest:
        largest = prod
        print(largest)

现在没有更多的错误了 - 但那是因为你将最后的4个,3个,2个和1个数字相乘。而这正是问题所在:你从未决定那里会发生什么。

所以,现在,你可以明确地做出决定。你想把它们算作批次,还是跳过它们?

如果你想进一步前进,你可以使用itertools编写滑动窗口分组函数,一个版本就像zip一样(当窗口的右边缘结束时停止)列表),一个像zip_longest一样的行为(仅当窗口的边缘熄灭时停止):

def groupwise(iterable, n):
    groups = itertools.tee(iterable, n)
    for i, group in enumerate(groups):
        next(itertools.islice(group, i, i), None)
    return zip(*groups)

def groupwise_longest(iterable, n, fillvalue=None):
    groups = itertools.tee(iterable, n)
    for i, group in enumerate(groups):
        next(itertools.islice(group, i, i), None)
    return itertools.zip_longest(*groups, fillvalue=fillvalue)

现在,您可以这样做:

for group_of_five in groupwise_longest(string, 5, 1):
    values = map(int, group)
    prod = reduce(operator.mul, values)
    if prod > largest:
        largest = prod
        print(largest)

然后,如果您决定不在最后比较不完整的组,只需将第一行更改为:

for group_of_five in groupwise(string, 5):

然后你可以将所有工作移到for循环之外:

groups = groupwise_longest(string, 5, 1)
intgroups = (map(int, group) for group in groups)
prods = (reduce(operator.mul, group) for group in groups)

现在我们有一系列产品,很明显要找到最高的产品,那就是:

print(max(prods))

例如:

>>> string = '12345678987654321'
>>> groups = groupwise(string, 5)
>>> intgroups = (map(int, group) for group in groups)
>>> prods = (reduce(operator.mul, group) for group in groups)
>>> max(prods)
28224

请注意,无处可出现一个错误或任何其他“小”错误。当然你仍然可以完全错误,或者根本不知道如何写它,但至少你的错误将是明显的大错误,这更容易调试。