/ / Iteratieren über eine Liste mit 8526 Items, die einen Index außerhalb des Bereichsfehlers erhalten - Python, Liste, Schleifen, Iteration

Iteratieren über eine Liste mit 8526 Items, die einen Index außerhalb des Bereichsfehlers haben - Python, Liste, Schleifen, Iteration

Python-Neuling hier. Ich habe an einem kleinen Skript gearbeitet, das XML in CSV für ein Projekt bei der Arbeit konvertiert. Es gibt 406 Elemente in den XML-Daten, die in den Speicher geparst wurden, und jedes Element hat 21 Indexfelder, die für dieses Element untergeordnet sind, was insgesamt 8.526 Indexfelder ergibt.

Von diesen 21 Indexfeldern für ein bestimmtes Element möchte ich die Punkte 0, 1, 2, 3, 5, 6, 7 und 8 ziehen.

Ich habe eine Schleife (ähnlich dem folgenden Code) erstellt, um Folgendes zu tun:

i = 0
files = 406
docrange = 8526
iterstep = 21
pad = "",""
for docs in range(i, docrange):
string1 = str("""+indexfields[iterstep])+pad)
string2 = str(indexfields[iterstep+1])+pad)
string3 = str(indexfields[iterstep+2])+pad)
string5 = str(indexfields[iterstep+3])+pad)
string6 = str(indexfields[iterstep+5])+pad)
string7 = str(indexfields[iterstep+6])+pad)
string8 = str(indexfields[iterstep+7])+pad)
string9 = str(indexfields[iterstep+8])+pad)
strung = string1+string2+string3+string5+string6+string7+string8+string9
print strung

iterstep = (iterstep + 21)
i = (i + 1)

Wenn ich diese Schleife betrete, erhalte ich den Fehler:

Traceback (most recent call last):
File "Path/To/My/script.py", line 55, in <module>
string1 = (str(indexfields[iterstep])) IndexError: list index out of range

Von dem, was ich erhalte, glaube ich nicht, dass ich die Liste modifiziere, die ich überspringe, wie andere Threads in Stack Overflow, die sich mit diesem Fehler befassen, darauf hindeuten.

Obwohl ich weiß, dass es weitaus elegantere Möglichkeiten gibt, den obigen Code zu schreiben, möchte ich die XML-Daten schnell in CSV konvertieren lassen und diesen Job in die richtige Reihenfolge bringen.

Edit1: Dies ist möglicherweise nicht der geeignete Ort dafür, aber hier ist ein Beispiel für die Datei Files.xml, aus der die Indexinformationen abgerufen werden. Es gibt eine andere XML-Datei, die in Verbindung mit Files.xml verwendet wird, ich kann dies bei Bedarf auch posten.

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<File>
<ExtendedProperties />
<ID>7514</ID>
<SyncFlag>Edit</SyncFlag>
<CustomSort />
<ViewerContext>None</ViewerContext>
<ProjectID>1</ProjectID>
<BoxID>0</BoxID>
<FileID>7514</FileID>
<FilePtr>0</FilePtr>
<Status>Active</Status>
<KeyValue />
<KeyVisualValue />
<Field>
<string>Some words that I would like to pull1</string>
<string>Some words that I would like to pull2</string>
<string>Some words that I would like to pull3</string>
<string>Some words that I would like to pull4</string>
<string>Nonsense</string>
<string>Some words that I would like to pull5</string>
<string>Some words that I would like to pull6</string>
<string>Some words that I would like to pull7</string>
<string>Some words that I would like to pull8</string>
<string>Some words that I would like to pull9</string>
<string>Nonsense</string>
<string>Nonsense</string>
<string />
<string />
<string />
<string />
<string />
<string />
<string />
<string />
<string />
</Field>
<Notes />
<DateStarted>2015-07-16T11:02:00</DateStarted>
<DateChanged>2015-12-09T14:46:58.7335221-05:00</DateChanged>
<ChangedBy>1</ChangedBy>
<Destruction>1990-01-01T01:00:00</Destruction>
<LabelPrinted>1990-01-01T01:00:00</LabelPrinted>
<SaveStyle>NewFile</SaveStyle>
<SaveNotesOnly>false</SaveNotesOnly>
<FileVerifyLevels>0</FileVerifyLevels>
<RemoteID>1</RemoteID>
</File>

Hier ist ein Snippit aus der Datei Documents.xml:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Document>
<ID>262601</ID>
<SyncFlag>Edit</SyncFlag>
<CustomSort />
<ViewerContext>None</ViewerContext>
<FileID>1647</FileID>
<RelProjectID>0</RelProjectID>
<ArchiveID>0</ArchiveID>
<Archive />
<DocumentID>262601</DocumentID>
<Status>Active</Status>
<Separator>Some words to pull</Separator>
<Divider>Some words to pull</Divider>
</Document>

Edit2: Einige großartige Antworten kamen von euch allen. Ich fand, dass die Ursache für meinen ursprünglichen Fehler darin lag, dass ein Iterationswert anfänglich auf 21 anstatt auf 0 gesetzt wurde. Ich brauche ein wenig mehr Anleitung mit dieser Software, wäre es besser, einen neuen Thread zu öffnen?

Antworten:

4 für die Antwort № 1

BEARBEITEN: Ihr Hauptaugenmerk sollte hier sein, zu lernen, wie man den Stack-Trace liest. Das bedeutet, dass Sie nach einer bestimmten Schleife versuchen, auf einen Index zuzugreifen, der noch nicht gefüllt ist. Versuchen Sie, die Indizes zu drucken, während Sie fortfahren, und sehen Sie, was passiert.

Für zukünftige Arbeiten würde ich stattdessen die Verwendung von XML Parsing empfehlen.

Sie sollten diese Konvertierung dynamisch handhaben, anstatt immer davon auszugehen, dass x Elemente vorhanden sind.

Python hat Module eingebaut, um XML zu analysieren und Xpath zu benutzen. https://docs.python.org/2/library/xml.etree.elementtree.html

Dadurch können Sie einzelne Knoten analysieren, auf Attribute zugreifen usw.


2 für die Antwort № 2

Ich glaube, dein Problem ist, dass du sagst, dass du es hast406 Reihen und 21 Elemente in jeder Reihe, insgesamt 8562 Elemente. Das bedeutet, dass Sie die Anzahl der Zeilen wiederholen müssen. Wenn Sie iterstep um 21, 8562 mal erhöhen, entspricht iterstep 179802, was dem 21-fachen der Anzahl der Elemente entspricht, die Sie haben. Sie müssen also Ihre Reichweite ändern auf range(i,files). Sie starten auch Ihren iterstep ab 21 wenn Sie es wahrscheinlich von Null anfangen müssen

files = 406
docrange = 8526
iterstep = 0
pad = "",""
for i in range(0, files):
string1 = str("""+indexfields[iterstep])+pad)
string2 = str(indexfields[iterstep+1])+pad)
string3 = str(indexfields[iterstep+2])+pad)
string5 = str(indexfields[iterstep+3])+pad)
string6 = str(indexfields[iterstep+5])+pad)
string7 = str(indexfields[iterstep+6])+pad)
string8 = str(indexfields[iterstep+7])+pad)
string9 = str(indexfields[iterstep+8])+pad)
strung = string1+string2+string3+string5+string6+string7+string8+string9
print strung

iterstep += 21

oder ein besserer Weg dies zu tun ist, iterstep zu entfernen und einfach xranges Schrittparameter und Schritt 21 jedes Mal zu verwenden

files = 406
docrange = 8526
pad = "",""
for i in range(0, docrange, 21):
string1 = str("""+indexfields[i])+pad)
string2 = str(indexfields[i+1])+pad)
string3 = str(indexfields[i+2])+pad)
string5 = str(indexfields[i+3])+pad)
string6 = str(indexfields[i+5])+pad)
string7 = str(indexfields[i+6])+pad)
string8 = str(indexfields[i+7])+pad)
string9 = str(indexfields[i+8])+pad)
strung = string1+string2+string3+string5+string6+string7+string8+string9
print strung

1 für die Antwort № 3

Das Problem wird sicherlich verursacht durch iterstep, Sie starten es von 21 und erhöhen es bei jeder Wiederholung um 21. Vielleicht solltest du es bei 0 behalten und du musst etwas mit dem machen i (weil das Ändern in der Schleife keinen Einfluss auf die range) oder entfernen Sie es vollständig.


1 für die Antwort № 4

Es sieht so aus, als ob Sie alle Ihre Daten in einem einzigen, GROSSEN, flachen Array namens indexfields.

Wenn ja, war das wahrscheinlich ein schlechter Ruf von Ihnen - Sie haben einige Informationen weggeworfen.

Unabhängig davon müssen Sie nun die Indexfelder in Gruppen von 21 Elementen durchlaufen. Das ist ziemlich einfach zu machen:

for i in range(0, len(indexfields), 21):

An diesem Punkt haben Sie i gleich einer Zahl, die ein Vielfaches von 21 ist. Sie extrahieren die Teilmenge der Felder, die Sie interessieren, mit den Index-Offsets, die Sie bereits bestimmt haben:

    offsets = (0,1,2,3,5,6,7,8)
fields = [indexfields[i+j] for j in offsets]

An diesem Punkt können Sie die Werte drucken oder sie in eine der vielen, vielen, vielen Bibliotheken einspeisen, die für die CSV-Dateimanipulation vorhanden sind. Hier ist eine einfache Print-to-Stout-Version:

    q = """
q_q = "",""
csv_line = q + q_q.join(fields) + q
print(csv_line)

Aufräumen:

# Fake up some data
indexfields = []

fake="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for i in range(0,406):
for j in range(0,21):
indexfields.append(str(i) + "-" + fake[j])

offsets = (0,1,2,3,5,6,7,8)
q = """
q_q = "",""

for i in range(0, len(indexfields), 21):
fields = [indexfields[i+j] for j in offsets]

csv_line = q + q_q.join(fields) + q
print(csv_line)