Problem mit "list index out of range"

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Hallo Leute!

Durchblicke leider die Fehlermeldung nicht ganz:

Code: Alles auswählen

Traceback (most recent call last):
  File "<pyshell#2>", line 2, in -toplevel-
    if buffer[i].find('!') is not -1:
IndexError: list index out of range
Das kommt bei folgendem Skript zu Stande:

Code: Alles auswählen

   for i in range(len(buffer)):    
        if buffer[i].find('!') is not -1:
            buffer.remove(buffer[i])
            
        if (buffer[i].find('<') is not -1):
            buffer.remove(buffer[i])
Der Buffer sieht so aus:
  • <DATA>
    ! comments
    80.6 1.612 39.420 0.3120 1.5320 4.7300 [all info available] 0. 1.0
    80.6 1.612 39.420 0.3120 1.5320 3.7300 [all info available] 0. 1.0
    83.9 1.714 63.160 2.1369 1.3288 2.1336 [all info available] 0. 1.0
    76.4 1.714 63.160 2.1369 1.3288 1.1336 [all info available] 0. 1.0
    31.3 1.800 37.683 17.7897 0.7563 1.2997 [all info available] 0. 1.0
    31.5 1.800 37.683 17.7897 0.7563 1.2997 [all info available] 0. 1.0
    31.5 1.800 37.683 17.7897 0.7563 1.2997 [all info available] 0. 1.0
    80.9 2.640 11.180 18.1656 1.0159 1.9906 [all info available] 0. 1.0
    <_DATA>
Was stimmt in meiner FOR Schleife nicht?


Danke für eure Hilfe.

Johannes
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Du iterierst bis len(buffer), d.h. bis zur Bufferlaenge zu Beginn der for-Schleife. Aber zwischendurch loeschst due Elemente von buffer, d.h. buffer wird kuerzer, sodass buffer[Bufferlaenge zu Beginn der for-Schleife] nicht mehr existiert...

range(len(buffer)) passt sich ja zwischendurch nicht an.
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Hi!

Wie kann ich die FOR Bedingung sinnvollerweise anpassen?

Danke,
Johannes
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

Hallo,

ich würde die for schleife sicheheitshalber in eine while schleife packen um nach jedem remove die Länge des buffer neu zu bestimmen, damit werden zwar alle bereits überprüften elemente von buffer noch einmal geprüft, was sicher kein guter Algorithmus ist, sollte aber solange buffer nicht soooo groß ist trotzdem in Ordnung sein.

in etwa so:

Code: Alles auswählen

run = True

while run:
   for i in range(len(buffer)):   
        if buffer[i].find('!') is not -1:
            buffer.remove(buffer[i])
	        break
           
        else if (buffer[i].find('<') is not -1):
            buffer.remove(buffer[i])
	        break

	    if i == range(len(buffer)):
	        run = False
	        break
möglichkeit 2:
das remove machst du in einer gesonderten for-schleife (bessere algorithmik)

Code: Alles auswählen

   i_remove = []
   for i in range(len(buffer)):   
        if buffer[i].find('!') is not -1:
            i_remove.append(i)
           
        else if (buffer[i].find('<') is not -1):
            i_remove.append(i)

   for j in i_remove:
	    buffer.remove(buffer[j])
kommt ganz drauf an was der rest des programmes macht...
Benutzeravatar
Mr_Snede
User
Beiträge: 387
Registriert: Sonntag 8. Februar 2004, 16:02
Wohnort: D-Dorf, Bo

kennst du

Code: Alles auswählen

enumerate 
schon?

Code: Alles auswählen

Puffer = [
   "80.6 1.612 39.420 0.3120 1.5320 4.7300 [all info available] 0. 1.0",
   "80.6 1.612 39.420 0.3120 1.5320 3.7300 [all info available] 0. 1.0",
   "83.9 1.714 63.160 2.1369 1.3288 2.1336 [all info available] 0. 1.0",
   "76.4 1.714 63.160 2.1369 1.3288 1.1336 [all info available] 0. 1.0",
   "31.3 1.800 37.683 17.7897 0.7563 1.2997 [all info available] 0. 1.0"
   ]

for i, Zeile in enumerate(Puffer):
   print "i:  ", i,
   print " Zeile: ", Zeile

# oder auch so:
for Zeile in enumerate(Puffer):
   print " Zeile 2ter Durchlauf: ", Zeile
Ich bemühe mich nicht aus Listen etwas zu löschen , über die ich gerade iteriere.
Ich hätte an deiner Stelle gleich eine Funktion gebastelt (ist nur Pseudocode):

Code: Alles auswählen

def bla(Puffer):
   rueckgabe_liste[]
   for Spalte in enumerate(Puffer):
      print " Spalte2ter Durchlauf: ", Spalte
      if alles OK:
         rueckgabe_liste.append(Spalte)

   return rueckgabe_liste

Zeige bitte auch mal einen Puffereintrag, der deine if-Abfragen auslöst.

cu Sebastian
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Hi Buell!

Ich bekomme jetzt immer noch diese Fehlermeldung:
  • Traceback (most recent call last):
    File "C: DA\Source\skript.py", line 29, in -toplevel-
    if buffer.find('!') is not -1:
    IndexError: list index out of range


Wieso kann diese If Abfrage if buffer.find('!') is not -1: einen Fehler machen?

LG
Johannes
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

die if abfrage an sich ist nicht das problem, die fehlermeldung sagt, dass deine Liste sozusagen zu Ende ist. Bsp: Liste hat 12 Elemente, so wäre das letzte Listenelement Liste[11] weil fängt ja bei 0 an und die for schleife versucht gerade auf zB Liste[12] zuzugreifen, was natürlich nicht vorhanden ist.

Probier mal folgendes:

mache wie im 1. bsp eine if abfrage (if i>=range(len(buffer))) in die for schleife und zwar an den Anfang der schleife (mit nem break drin)!!! Wenn das noch nicht funktioniert, dann verändere diese Abfrage so: if i>=range(len(buffer)) - 1
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Hallo Sebastian!

Was meinst du genau als Buffer-Eintrag:

Der Buffer kommt so zustande:

Code: Alles auswählen


    buffer=[]

    in_data = False
    
    for line2 in file(input):
          if "< DATA_ >" in line2:
            in_data = True
            line2 = line2[line2.find("< _DATA >")+9:]
          if in_data:
            buffer.append(line2)
          if "< _DATA >" in line2:
            break
Das Inputfile sieht so aus:
  • <DATA>
    ! comments
    80.6 1.612 39.420 0.3120 1.5320 4.7300 [all info available] 0. 1.0
    80.6 1.612 39.420 0.3120 1.5320 3.7300 [all info available] 0. 1.0
    83.9 1.714 63.160 2.1369 1.3288 2.1336 [all info available] 0. 1.0
    76.4 1.714 63.160 2.1369 1.3288 1.1336 [all info available] 0. 1.0
    31.3 1.800 37.683 17.7897 0.7563 1.2997 [all info available] 0. 1.0
    31.5 1.800 37.683 17.7897 0.7563 1.2997 [all info available] 0. 1.0
    31.5 1.800 37.683 17.7897 0.7563 1.2997 [all info available] 0. 1.0
    80.9 2.640 11.180 18.1656 1.0159 1.9906 [all info available] 0. 1.0
    <_DATA>

Wäre super, wenn du mir weiterhelfen könntest.

LG
Johannes
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

...wenn ich das so sehe bin ich mir nicht so ganz sicher ob buffer der richtig gewählte bezeichner ist. Du erzeugst doch nur ne ganz normale Liste von Strings, wozu dann buffer?
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Hi Buell!

So gehts nicht. Hab anscheinend was nicht ganz verstanden von deiner Erklärung.

Code: Alles auswählen


    while run: 
       for i in range(len(buffer)):    
            if i>=range(len(buffer)): 
                buffer.remove(buffer[i]) 
                break 
                
            elif i>=range(len(buffer)): 
                buffer.remove(buffer[i]) 
                break 

            if i == range(len(buffer)): 
                run = False 
                break

Kannst du das bitte anpassen, so wie du das gemeint hast.

Recht herzlichen Dank für deine Unterstützung,

Johannes
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Bin noch blutiger Anfänger. Habs mit den Bezeichnungen noch nicht so ganz. War offensichtlich eine falsche Bezeichnung. Sorry.
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

gemeint hatte ich es etwa so:

Code: Alles auswählen

    while run:
       for i in range(len(buffer)):   
            if i>=range(len(buffer)):
                run = False
                break
               
            if buffer[i].find('!') is not -1:
                buffer.remove(buffer[i])
                break
           
            else if (buffer[i].find('<') is not -1):
                buffer.remove(buffer[i])
                break
wenn das nicht geht die Zeile:

Code: Alles auswählen

if i>=range(len(buffer)):
durch das ersetzen:

Code: Alles auswählen

if i>=range(len(buffer))-1:
wegen dem Bezeichner, bin mir nicht so sicher ob du wirklich einen Buffer benötigst, eigentlich könntest du auch jeden anderen Bezeichner verwenden um einfach eine Liste zu generieren. buffer ist ja ein Bezeichner für ein Buffer Object:

def:
Python objects implemented in C can export a group of functions called the ``buffer interface.'' These functions can be used by an object to expose its data in a raw, byte-oriented format. Clients of the object can use the buffer interface to access the object data directly, without needing to copy it first.

Two examples of objects that support the buffer interface are strings and arrays. The string object exposes the character contents in the buffer interface's byte-oriented form. An array can also expose its contents, but it should be noted that array elements may be multi-byte values.

An example user of the buffer interface is the file object's write() method. Any object that can export a series of bytes through the buffer interface can be written to a file. There are a number of format codes to PyArg_ParseTuple() that operate against an object's buffer interface, returning data from the target object.

More information on the buffer interface is provided in the section ``Buffer Object Structures'' (section 10.7), under the description for PyBufferProcs .

A ``buffer object'' is defined in the bufferobject.h header (included by Python.h). These objects look very similar to string objects at the Python programming level: they support slicing, indexing, concatenation, and some other standard string operations. However, their data can come from one of two sources: from a block of memory, or from another object which exports the buffer interface.

Buffer objects are useful as a way to expose the data from another object's buffer interface to the Python programmer. They can also be used as a zero-copy slicing mechanism. Using their ability to reference a block of memory, it is possible to expose any data to the Python programmer quite easily. The memory could be a large, constant array in a C extension, it could be a raw block of memory for manipulation before passing to an operating system library, or it could be used to pass around structured data in its native, in-memory format.
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Danke für deine ausführliche Antwort!

Irgendwie bekomm ich das einfach nicht zum Laufen. Bei der ersten Version kommt es anscheinend zu einer Endlosschleife.

Bei der zweiten Version bekomm ich diese Fehlermeldung:


Traceback (most recent call last):
File "C:\DA\Source\tabelle.py", line 30, in -toplevel-
if i>=range(len(buffer))-1:
TypeError: unsupported operand type(s) for -: 'list' and 'int'


Da passt was nicht.
Tut mir leid, dass ich mich so ungeschickt anstelle.

Danke nochmals,
Johannes
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

...kein problem bin auch kein python guru ;)

ja, fehlermeldung ist klar, man kann nicht einfach nen integer Wert von einem List-Operator abziehen ...

versuch mal so:

Code: Alles auswählen

if i not < range(len(buffer)):
sonst ganz anders:

Code: Alles auswählen

j = 0
removes = []
for i in buffer:
    if i.find('!') is not -1:
        removes.append(j)

    else if i.find('<') is not -1:
        removes.append(j)
    j += 1

for i in removes:
    buffer.remove(buffer[i])
...sonst fällt mir nix mehr ein, außer buffer nicht so zu nennen

PS: mir fällt grad auf das obere von mir ist Blödsinn, ist ja das selbe wie if i == ...
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Hi Leute!

Irgendwie bekomm ich das nicht auf die Reihe:

Code: Alles auswählen

run=True
    
    while run: 
       for i in range(len(buffer)):    
            if i < range(len(buffer)):
                run = False 
                break 
                
            if buffer[i].find('!') is not -1: 
                buffer.remove(buffer[i]) 
                break 
            
            if (buffer[i].find('<') is not -1): 
                buffer.remove(buffer[i]) 
                break


Das Skript läuft, aber die Elemente der Liste in welchen '!' oder '<' vorkommen werden nicht gelöscht.

Woran liegt das?

Lg
Johannes
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Wie kann man das lösen, damit ich die Elemente aus meiner Liste gelöscht werden in welchen nicht '!' oder '<' vorkommt.

Wie kann da ein kurtzes Skript aussehen?

Danke,
Johannes
keboo
User
Beiträge: 132
Registriert: Sonntag 19. Februar 2006, 14:03

Ich hatte gerade die Idee, dass Problem bereits beim Einlesen zu lösen.

Das Einleseskript sieht so aus:

Code: Alles auswählen


in_data=False
    for line2 in file(input):
        if "< DATA_ >" in line2:
            in_data = True
            line2 = line2[line2.find("< _DATA >")+9:]
            
        if in_data:
            buffer.append(line2)
            
        if "< _DATA >" in line2:
            break

Wie kann ich dieses Skript verändern, damit die Zeilen in welchen '!' und '<' vorkommen erst gar nicht eingelesen werden?

Danke,

Johannes
Antworten