2013-06-18 65 views
2

我有一個快速搜索,但無法找到任何有助於我的問題。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:字符串索引超出範圍」。誰能幫忙?

+1

這已經是一個很好的,書面質詢,但對於未來的參考,它本來如果甚至更好,而不是讓整出來,你有沒有和較小的整數(比如12345678987654321)測試,並驗證它有一樣的問題。然後你可以發佈完成,運行(直到你想要幫助的錯誤)代碼,並描述預期的輸出,而不是解釋你爲什麼給我們不完整的代碼。 – abarnert

回答

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) 
+0

-1:謹慎解釋你的改變? – kay

+0

我剛剛完成了。 –

+1

-1已刪除,但它應該是'-5'。 – kay

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 

,並注意有無處你可以做一個關閉的情況的一個錯誤,或任何其他「小」的錯誤。當然,你仍然可以得到完全錯誤的東西,或者根本不知道如何編寫它,但至少你的錯誤將是明顯的大錯誤,更容易調試。

+0

順便提及,在通過我的計算機上的各種項目的快速搜索,groupwise'的'變化(其可以被看作是pairwise'的'從迭代工具食譜,或從''more_itertools' chunked'泛化)是已知的作爲'windowed','slide'和'n_wise' ... – abarnert