2016-11-10 1 views
0

J'essaye de calculer la surface d'un fichier avec des nombres de format RLE (exécuter le codage de longueur) en utilisant PYTHON. J'ai des problèmes avec mes déclarations FOR et IF.Boucle sur les causes de la liste IndexError - Python

enter image description here

Je suis en train de calculer la surface des cellules contenant la valeur 201.

My current error:

Traceback (most recent call last): 
    File "D:\2016-2017\Fall2016\SpatialDataStructures\Labs\Lab4\Area_Calc_from_RLE.py", line 68, in <module> 
    if cellValuesAsIntList[i] == 201: 
IndexError: string index out of range 

Here is the file I am working with:

ncols   40 
nrows   40 
xllcorner  -2.3036649208516 
yllcorner  -1.1518324594945 
cellsize  25 
NODATA_value -9999 
13, 0, 1, 201, 26, 0, 1, 3, 12, 0, 1, 201, 39, 0, 1, 201, 39, 0, 1, 201, 39, 0, 2, 201, 33, 0, 4, 501, 2, 0, 2, 201, 32, 0, 4, 501, 3, 0, 3, 201, 29, 0, 5, 501, 5, 0, 2, 201, 26, 0, 7, 501, 6, 0, 1, 201, 25, 0, 8, 501, 6, 0, 1, 201, 25, 0, 7, 501, 7, 0, 1, 201, 25, 0, 6, 501, 8, 0, 1, 201, 25, 0, 6, 501, 8, 0, 1, 201, 6, 0, 4, 102, 15, 0, 7, 501, 7, 0, 1, 201, 6, 0, 6, 102, 14, 0, 7, 501, 5, 0, 2, 201, 6, 0, 6, 102, 15, 0, 6, 501, 5, 0, 1, 201, 7, 0, 5, 102, 16, 0, 6, 501, 5, 0, 1, 201, 7, 0, 4, 102, 18, 0, 8, 501, 2, 0, 5, 201, 3, 0, 3, 102, 19, 0, 9, 501, 5, 0, 2, 201, 25, 0, 8, 501, 6, 0, 1, 201, 29, 0, 4, 501, 6, 0, 1, 201, 29, 0, 4, 501, 6, 0, 1, 201, 9, 0, 1, 501, 5, 102, 15, 0, 2, 501, 7, 0, 1, 201, 9, 0, 6, 102, 23, 0, 2, 201, 8, 0, 1, 501, 6, 102, 3, 0, 4, 202, 15, 0, 2, 201, 4, 0, 6, 501, 6, 102, 2, 0, 2, 202, 2, 0, 8, 202, 5, 0, 4, 201, 4, 0, 8, 501, 4, 102, 3, 0, 1, 202, 5, 0, 2, 202, 3, 0, 6, 202, 1, 201, 7, 0, 8, 501, 2, 102, 1, 501, 21, 0, 1, 201, 6, 0, 11, 501, 22, 0, 1, 201, 6, 0, 8, 501, 25, 0, 1, 201, 6, 0, 8, 501, 25, 0, 1, 201, 1, 101, 5, 0, 8, 501, 25, 0, 1, 201, 1, 101, 5, 0, 8, 501, 14, 0, 3, 101, 8, 0, 1, 201, 1, 101, 5, 0, 11, 501, 12, 0, 4, 101, 6, 0, 2, 201, 1, 101, 4, 0, 12, 501, 11, 0, 4, 101, 6, 0, 1, 101, 1, 201, 1, 101, 4, 0, 12, 501, 21, 0, 1, 101, 1, 201, 5, 0, 11, 501, 23, 0, 1, 201, 5, 0, 8, 501, 26, 0, 1, 201, 5, 0, 8, 501, 26, 0, 1, 201, 5, 0, 7, 501, 27, 0, 1, 201, 5, 0, 8, 501, 8, 0 

This is my code:

fi = open(r'D:\2016-2017\Fall2016\SpatialDataStructures\Labs\Lab4\Data\AsRLE.txt','r') 
fileLines = fi.readlines() 
fi.close 
#--------------------------------------------------------------------- 

#--------------------------------------------------------------------- 
#Populated variables required for code from fileLines variable 
cellValuesAsString = [] 
lineNum = 0 
for line in fileLines: # for each line the FileLines List 
    # get number of cols, ncols, i.e. the 1st line in the file 
    if lineNum == 0: 
    ncols = int(line[14:]) 
    # get number of rows, nrows, i.e. the 2nd line in the file 
    elif lineNum == 1: 
    nrows = int(line[14:]) 
    # get cell size, cellsize, i.e. the 5th line in the file 
    elif lineNum == 4: 
    cellsize = int(line[14:]) 
    # get cell values in RLE format as String, , i.e. the 7th line in the file 
    elif lineNum == 6: 
    cellValuesAsString = line 
    lineNum = lineNum + 1 

# removes spaces 
cellValuesAsString = cellValuesAsString.replace(" ", "") 

# convert string into a list of strings split by comma 
cellValuesAsStringList = cellValuesAsString.split(',') 

# convert strings to integers 
cellValuesAsIntList = cellValuesAsStringList 
for index, item in enumerate(cellValuesAsStringList): 
    cellValuesAsIntList[index] = int(cellValuesAsStringList[index]) 
#--------------------------------------------------------------------- 

#THIS IS WHERE YOU WRITE YOUR CODE 

#--------------------------------------------------------------------- 
cellCode = 201 
codeArea = 0 

area = 0 
npixels = 0 
i = 1 

for cellValuesAsIntList in line: 
    if cellValuesAsIntList[i] == 201: 
    b = cellValuesAsIntList[i-1] 
    npixels = npixels + b 
    else: 
    i=i+2 




print npixles 
print "Area: " + npixels * cellSize 
+1

Où est 'nouveau défini coût média? –

+0

@ kiran.koduru bien, j'essaie de comprendre ce qu'il faut mettre là. Je veux faire une boucle dans le tableau. J'ai des problèmes quelles valeurs mettre dans l'instruction FOR. – Tristan

+0

Vous devez construire votre programme étape par étape. Vous ne pouvez pas coller une goutte de texte et demander à quelqu'un de l'écrire pour vous. La boucle 'for' est utilisée pour itérer' iterables' dans python '' strings', 'list',' tuples', 'dictionaries' sont tous des itérations. –

Répondre

0

Cela ressemble à un grand effort. Votre problème est que vous êtes à court d'indices, ce qui augmente le IndexError. Bien que votre situation nécessite que chaque élément soit légèrement indexé, heureusement, vous n'avez qu'à interroger la valeur précédemment itérative.

Pour de telles situations, essayez le suivi de la valeur précédente:

npixels = 0 
cells = cellValuesAsIntList       # for clarity 

prev = None 
for cell in cells: 
    if cell == 201: 
     npixels += prev        # increment operator 
    prev = cell 

En règle générale, les indices Évitez et modificatrices itération. Bien que ce ne soit pas votre problème direct, cette pratique peut provoquer de nombreux effets secondaires. Si possible, effectuez une itération directe d'une séquence et travaillez avec chaque élément itéré. Évitez de modifier les indices par d'autres moyens, par ex. inverser l'itération, muter une séquence copiée ou utiliser des compréhensions.

0

Supposons que vous ayez:

>>> rle=[2,5,1,8,6,9,3,30,6,22,2,12] 

Vous pouvez transformer en tuples de longueur de course comme ceci:

>>> zip(*[iter(rle)]*2) 
[(2, 5), (1, 8), (6, 9), (3, 30), (6, 22), (2, 12)] 

Ensuite, vous pouvez filtrer les valeurs contenant une valeur cible (je vais utiliser même 2 bien que vous mentionniez 201 comme cible car votre exemple ne contient pas 201):

>>> filter(lambda t: t[0]==2, zip(*[iter(rle)]*2)) 
[(2, 5), (2, 12)] 

Appliquez ensuite que votre fichier:

with open(file_name) as f_in: 
    for line in f_in: 
     li_as_ints=map(int, line.split(",")) 
     fl=filter(lambda t: t[0]==201, zip(*[iter(li_as_ints)]*2)) 
     # produces all the values, expanded, with 121 as value... 

S'il vous plaît ne pas faire quelque chose le long de ces lignes:

fh=open(a_file_name) 
lines=fh.readlines() 
for line in lines: 
    #process a line 

Vous lisez inutilement le fichier entier.

Au lieu de cela faire:

with open(a_file_name) as f_in: 
    for line in f_in: 
    # process a line 
+0

Élégant. En Python 3, vous auriez besoin de >>> liste (zip (* [iter (rle)] * 2)) '. – pylang

+0

Seulement pour afficher les résultats. Pour la dernière boucle, bien sûr, vous pouvez juste parcourir le résultat de 'filter' ... – dawg

+0

Vous avez raison, même si par souci de clarté, pour obtenir le résultat que vous avez posté,' list() 'serait nécessaire. – pylang