Frage zur Listenverarbeitung

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.
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Hallo zusammen,

ich lese eine csv-Datei aus und muss einzelne Listenelemente ersetzen.

Code: Alles auswählen

for line in f:
    line.replace(' ','')
    z = line.split(';')
    z[12].replace('1','ZV')\
        .replace('2','R')\
        .replace('4','ZB')\
        .replace('5','BR')\
        .replace('6','SO')\
        .replace('14','ZV')
    print z
warum bekomme ich folgende Fehlermeldung?: :oops:

Code: Alles auswählen

z[12].replace('1','ZV')\
IndexError: list index out of range
Stephan
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi Stephan,

hat z nach dem split wirklich 13 Elemente?
Im übrigen hast Du da noch einen Fehler drinnen, erst wird "1" durch "ZV" ersetzt und dann wird versucht "14" durch "ZV" zu ersetzen was aber nicht gehen wird, da ja 1 schon durch ZV ersetzt wurde.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
joe

Hi!
Stephan hat geschrieben: warum bekomme ich folgende Fehlermeldung?: :oops:

Code: Alles auswählen

z[12].replace('1','ZV')\
IndexError: list index out of range
Weil z offensichtlich keine 13 elemente enthält. Ist die letzte zeile in der datei vielleicht eine leerzeile?
joe
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Hallo Dookie, Hallo Joe,

ich habe in der csv-Datei 41 Zeilen und es sind keine Leerzeilen enthalten.
Jede Zeile hat 37 Elemente. Da sind aber auch ne Menge leere dabei. das sollte aber kein Problem sein, da alle Elemente in csv durch ";" getrennt sind. Das 13. Element ist meistens leer.

In der Ausgabe von

Code: Alles auswählen

print z[12] 
wird eine Leerzeile zugefügt und es wird nichts ersetzt. :?

Code: Alles auswählen

Liste ok
6
1
5
4
4
4
4
2
1
5
4
2

6
1
5
4
2


Stephan
joe

Hallo!
Stephan hat geschrieben:In der Ausgabe von

Code: Alles auswählen

print z[12] 
wird eine Leerzeile zugefügt und es wird nichts ersetzt. :?
z[12] ist (wenn vorhanden) ja ein string und strings sind unveränderlich, d.h. daß replace() das string-objekt nicht direkt ändern kann, sondern den veränderten string als neues objekt zurückgibt: z[12] = z[12].replace('1','ZV')
joe
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

und sehe ich das richtig? enthält z[12] wenn überhaupt was enthalten ist eh immer eine Zahl, dann könnte man das ganze auch mit einem Dictionary lösen:

Code: Alles auswählen

replacer12 = {"1" : "ZV",
              "2" : "R",
              "4" : "ZB",
              "5" : "BR",
              "6" : "SO",
              "14" : "ZV"}

for line in f:
    line.replace(' ','')
    z = line.split(';')
    z[12] = replacer12.get(z[12], z[12])
    print z
Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Danke für die Hilfe. Ich werde das mit dem Dic mal probieren.
Was ich nicht verstehe ist, dass folgendes einen fehler erzeugt:

Code: Alles auswählen

for line in f:
    b = b + 1
    line.replace(' ','')
    z = line.split(';')
    print 'Zeile: %s'%b
    print z[12]
Fehler:

Code: Alles auswählen

print z[12]
IndexError: list index out of range
aber folgendes funktioniert:

Code: Alles auswählen

for line in f:
    b = b + 1
    line.replace(' ','')
    z = line.split(';')
    print 'Zeile: %s'%b
    print z[12:13]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

mach mal:

Code: Alles auswählen

for line in f:
    b = b + 1
    line.replace(' ','')
    z = line.split(';')
    print 'Zeile: %i Eintraege: %i' % (b, len(z))
    print z
    print z[12]

Dookie
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

... da liegt der Hase im Pfeffer

In der csv-Datei werden verschiedene Zeilen (die sehr lang sind) gebrochen (mit "\n"). Dadurch ist dann eine Zeile nur 11 Elemente lang (da es nur der Rest der vorhergehenden Zeile ist).

Ist natürlich ziemlich doof von Excel. :o

Kann ich schon beim Einlesen die Zeilen reduzieren? ich benötige nur Informationen aus den ersten 26 Spalten.

Stephan
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Code: Alles auswählen

for line in f:
    z = line.replace(" ","").split(";", 26)
    ...
Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Danke - ich sehe langsam Licht am Ende des Tunnels :wink:

Stephan
joe

Hallo!
Dookie hat geschrieben:

Code: Alles auswählen

for line in f:
    z = line.replace(" ","").split(";", 26)
    ...
Das hilft ihm nicht viel, denn das verhindert ja nicht die auswertung der zeilen mit nur elf werten, die ja eigentlich nur der rest der vorherigen zeile sind. Ich würd eher diese zeilen überspringen (wenn sicher ist, daß diese "rest"-zeilen selbst nie 26 oder mehr werte enthalten können):

Code: Alles auswählen

for line in f:
    ...
    z = line.split(';')
    if len(z) < 26: continue
    ...
Das wäre mir aber alles zu unsicher. Ich würde eher das übel an der wurzel zu packen versuchen. Ich kann hier zumindest problemlos gigantische exceltabellen als csv-dateien exportieren, ohne daß irgendwelche zeilenumbrüche entstehen. Kann das problem nicht irgendwo zwischen dem excel-export und dem python-script entstanden sein? Emailprogramme z.B. versehen versandte textdateien gerne mit zusätzlichen umbrüchen.
Falls du, Stephan, auf die exceltabelle einfluß hast, könntest du auch jede zeile in z.B. eckige klammern einschließen. Dann kannst du im python-script klar identifizieren, was zu einer datenzeile gehört.
joe
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Hallo Joe,

das Problem muss schon in Excel sein, denn wenn ich die csv-Datei mit WordPad oder einem anderen Texteditor öffne, habe ich Zeilenumbrüche. Nur wenn ich die Datei mit NotePad öffne, sind die Zeilen komplett.

Python liest die Zeilen wie WordPad ein.

Stephan
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Frage: warum verwendest du nicht das Standartdistrimodul csv? Das lässt sich auch so konfigurieren, dass du mit ";" als Seperator arbeiten kannst. Du spaarst dir damit bestimmt eine Menge Arbeit :wink: ...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Hallo Milan,

gibt es zu diesem Modul eine brauchbare Beschreibung in deutsch?


Stephan
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Auf die schnelle: nein, fällt mir nix ein... aber du kannst ja selber mal suchen bzw dir den Thread durchlesen. Da ist unter anderem ein Anwendungsbeispiel mit drin, vielleicht hilft dir das beim verstehen. Grundprinzip ist, dass ein Fileobj einer Readerklasse übergeben wird. Diese Readerklasse kann als Argument zu for-schleifen genutzt werden, wobei dann immer die einzelnen Werte als Liste genutzt werden können. Eine Datei, in der das hier steht:

Code: Alles auswählen

1,2,3
4,5,6
"aha, aha","lalala",xyz
kann dann so behandelt werden:

Code: Alles auswählen

import csv
f=file(...)
reader=csv.reader(f) # kein Dialekt, wie bei Exel notwendig wäre, hier werden "," verwendet
for werte in reader:
    print repr(werte)
f.close()
Selbst das Komma in Anführungszeichen wird korrekt geparst, da es als Teil des Strings und nicht als Trennzeichen angesehen wird.
joe

Milan hat geschrieben:

Code: Alles auswählen

reader=csv.reader(f) # kein Dialekt, wie bei Exel notwendig wäre, hier werden "," verwendet
Bei Stephans ssv-dateien (semicolon separated values) ginge das dann so:

Code: Alles auswählen

reader = csv.reader(f),delimiter=';')
Aber helfen tut ihm das alles nix, denn mit seinen kaputten dateien wird das csv-modul genauso wenig klar kommen.
joe
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Das glaubeich nicht so ganz... ich hab zwar das hier überlesen:
Stephan hat geschrieben:... da liegt der Hase im Pfeffer

In der csv-Datei werden verschiedene Zeilen (die sehr lang sind) gebrochen (mit "\n"). Dadurch ist dann eine Zeile nur 11 Elemente lang (da es nur der Rest der vorhergehenden Zeile ist).

Ist natürlich ziemlich doof von Excel. :o
Aber das Notepad die Zeilen orginalgetreu einließt gibt mir zu denken:
Stephan hat geschrieben:... mit WordPad oder einem anderen Texteditor öffne, habe ich Zeilenumbrüche. Nur wenn ich die Datei mit NotePad öffne, sind die Zeilen komplett.
Ich vermute, da ist ein Teil der Daten binär gespeichert wurden, sodass da ein Fehler liegt (es wäre sehr nützlich, die Datei mal in binärer Repräsentation ausschnittsweise zu sehen). Selbst wenn das so sein sollte, kann er mit csv aber schon mal den Dialekt genau spezifizieren. Am besten wäre es vielleicht einmal zu testen, was er ohne Dialekt sagt, denn csv verwendet einen Sniffer, der versucht auszukunden, was für ein Dialekt vorliegt. Eventuelle gibt es Probleme mit den Zeilenumsprüngen (binär halt).

Ansonsten könnte es helfen, die Zeilenumsprünge rauszunehmen und immer neu nach 37 ";" einzusetzen.
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Hallo Milan,

ich habe mich mal etwas mit der csv-Datei beschäftigt.
Das Problem ist, dass in der xls-Datei in einigen Zellen Text mit Zeilenumbruch eingegeben ist. Ich kann zwar die Formatierung ändern indem ich in Excel das Häkchen bei Zeilenumbruch entferne, aber in der Bearbeitungsleiste wird der Text immer noch in zwei Zeilen angezeigt. Dieser Zeilenumbruch führt in der csv-Datei zu einer neuen Zeile.


Stephan
Antworten