Daten in Array oder Liste speichern

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
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo zusammen,

ich lese Zeilen aus einer Datei ein und möchte diese Zahlen in einem Array oder einer Liste speichern. Wie macht man das am Besten in Python?

Code: Alles auswählen

while line != -1:
     line = fid.readline()
     line = string.split(line)
     #print line
     first_line = line[0]
     if first_line.rstrip() == 'blabla':
     
        co_x = line[2]
        co_y = line[3]
        co_z = line[4]  
        print co_x
        print co_y
        print co_z
Also co_x soll in die erste Spalte, co_y in die zweite und co_z in die dritte. Dann soll die nächste Zeile darunter angehängt werden...
detlef
Zuletzt geändert von Anonymous am Freitag 26. Oktober 2012, 13:51, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,

also ich muss doch ein Array verwenden, weil meine Routine die Koordinaten für weitere Programme bereitgestellt werden müssen.
Also ein Array
x1 y1 z1
x2 y2 z2
usw.

detlef
BlackJack

@01detlef: Erstelle eine Liste und in jedem Schleifendurchlauf hängst Du fügst Du dort eine Liste mit den Werten an. Spalten und so etwas wie „nächste Zeile darunter” macht da wenig Sinn, denn eine Struktur im Speicher ist etwas anderes als eine *Darstellung* dieser Struktur. Das was Du möchtest ist klingt einfach nach einer verschachtelten Struktur aus Listen.

Funktionen aus dem `string`-Modul, die auch als Methoden auf Zeichenketten existieren, sind veraltet und sollten nicht mehr verwendet werden.

Du solltest die ``while``-Schleife durch eine ``for``-Schleife über die Zeilen des Dateiobjekts ersetzen und `line` nicht an so verschiedene Datentypen binden. `row` bietet sich zum Beispiel als Name an.

`first_line` ist ein schlechter Name für das erste Element einer Zeile. Der Name suggeriert es handle sich bei dem Objekt selbst um eine Zeile.

Und was meinst Du mit Array? Python hat Listen als grundlegenden Sequenztyp. Es gibt zwar auch ein `array`-Modul, aber dessen Zweck ist es die Umwandlung von Sequenzen von gleichartigen Binärdaten von und nach Python-Objekte zu erleichtern.

Daneben gibt es noch `numpy`-Arrays. Da ist jetzt die Frage welche Datenmengen erwartest Du, welche Operationen sollen darauf ausgeführt werden, und was ist mit bereitstellen für andere Programme gemeint, um entscheiden zu können ob `numpy` notwendig oder sinnvoll ist.
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,

genau, es soll ein numpy-array sein. Es werden mit dem Array dann Berechnungen durchgeführt und deshalb ist es wichtig, dass ich ein numpy-Array mit drei Spalten (x,y,z) erstelle.

Code: Alles auswählen

i=0
j=2
level = {}
while line != -1:
     line = fid.readline()
     line = string.split(line)
     #print line
     first_line = line[0]
     if first_line.rstrip() == 'blabla':
     
        co_x = line[2]
        co_y = line[3]
        co_z = line[4] 
        for j in range (4):
                 level[(i,j)] = line[j]
     i=i+1
Ich habe an sowas gedacht, aber da kommt er mit den Klammern immer nicht klar?!??! Was ist daran falsch?

detlef
BlackJack

@01detlef: Mit welchen Klammern? Und was ist mit den anderen Hinweisen das etwas sauberer und kürzer zu schreiben? Was soll diese unsinnige Bedingung beim ``while``? Und poste doch bitte lauffähige Beispiele — hier haut es einem einen `NameError` um die Ohren weil `line` benutzt wird bevor es definiert wurde. Warum wird `j` vor der ``while``-Schleife an einen Wert gebunden der nie verwendet wird?

Wenn Du ein Array haben möchtest, aber erst eine Datenstruktur mit Grundtypen als Zwischenschritt erstellen willst, dann ist immer noch eine verschachtelte Listenstruktur das Mittel der Wahl und kein Wörterbuch. Die „slicing syntax” auf Listen wäre vielleicht auch einen Blick wert. Und Du musst die Datenelemente auch in den entsprechenden Typen umwandeln. Mit Zeichenketten kann man schlecht rechnen.
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,

also das habe ich mir so bisher ausgedacht und kann sehr viel Blödsinn sein.

Ich habe eine Datei in der manche Zeilen mit einem Buchstaben anfangen und danach kommen Koordinaten, die ich in eine Matrix einlesen möchte:

Textfile:
Name 1 x y z
Name 2 x y z
usw
Diese Sachen habe ich eingelesen mit:

Code: Alles auswählen

fid = open(dateiname,'r')
#prüft ob integer erstellt werden kann
def p(v):
  try:
    return float(v)
  except ValueError:
    return v
while True:
  line = fid.readline()
  if not line: 
       break
  line = string.split(line)
  first_line = line[0]
  if first_line.rstrip() == 'GRID':
      out = line[2:]
      coordinates = ([p(i) for i in out])
      #print coordinates[0]
fid.close()

Soweit bin ich gerade und nun sollen die Daten in eine Matrix, weil das für die weitere Verarbeitung nötig ist. Eine Matrix, die man dann mit Daten[j] ansprechen kann. j soll von 0 bis 2 laufen für x,y,z und i so viele wie Koordinaten da sind.

Mich würde interessieren, wie man das am geschicktesten machen kann? Kann ich auf den obigen Code aufbauen oder ist das auch schon Blödsinn?

detlef
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo detlef,

in Python liest man üblicherweise Dateien zeilenweise mit einer for-Schleife:

Code: Alles auswählen

fid=open(dateiname)
for line in fid:
    do_something
fid.close()
statt string.split(line) sollte line.split() verwendet werden.
Das nachfolgende rsplit ist überflüssig, da split schon alle
Leerzeichen vor und nach jedem Teilstring entfernt.
Bei leeren Zeilen liefert split eine leere Liste, so dass der
Versuch auch line[0] zuzugreifen mit einem IndexError belohnt wird.

Code: Alles auswählen

if line and line[0].upper()=='GRID':
ist deutlich robuster und fehlertoleranter.

Warum ignorierst Du den ValueError? Spätestens wenn Du mit
den Coordinaten rechnen willst, wird sich Dein Programm ärgern.
Fehler so früh wie möglich anzeigen, dann kann man die Ursache
besser lokalisieren.

Alles in allem:

Code: Alles auswählen

coordinates = []
fid = open(dateiname)
for line in fid:
    line=line.split()
    if line and line[0].upper()=='GRID':
        coordinates.append(map(float,line[2:]))
fid.close()
Grüße
Sirius
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,

vielen Dank. Ich habe nun leider kein Python parat, aber kann ich damit dann z.b. coordinates[2][2] später benutzen, wenn ich die z-Komponente von der dritten Koordinate haben möchte? Das ist nämlich das Format was ich später brauche, also ein doppeltes array, dass man so ansprechen kann.

detlef
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Sirius3 hat geschrieben:

Code: Alles auswählen

fid=open(dateiname)
for line in fid:
    do_something
fid.close()
Vor allem nutzt man in Python das "ContextManager"-Interface aus, wenn ein Objekt es zur Verfügung stellt, wie etwa das ``file``-Objekt. Also kann das die Dateioperationen in einem ``with`` -Block schreiben:

Code: Alles auswählen

with open(...) as handler:
    # handler ist hier an das file-object gebunden
Vorteil: Die Datei wird immer, also auch bei Exceptions, geschlossen!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,
ich muss es nochmal probieren. Der Code wird jetzt wahrscheinlich nicht laufen, aber ich würde mal gerne wissen, wieso sowas vom Prinzip nicht verwendbar ist. Das ganze erinnert mich mehr an Matlab und deshalb möchte ich sowas wohl lieber machen...

Code: Alles auswählen

coordinates = []
s=1
i=0
j=0
fid = open(dateiname)
for line in fid:
    line=line.split()
    if line and line[0].upper()=='GRID':
        for j in range(2):
           coordinates[i][j]=line[s]
           s=s+1
    s=1
fid.close()
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Vllt als Erklärung: Ich möchte die Liste/Matrix/Array übergeben und dann muss es möglich sein mit coordinates[j] auf die Einträge zuzugreifen. Deshalb möchte ich gerne diese Form erzeugen.

detlef
BlackJack

@01detlef: Das geht nicht weil man per Index nicht auf nicht existierende Listenelemente zugreifen kann, also auch nichts zuweisen kann. Und schon gar nicht kann man auf diese Weise magische Unterlisten durch Zuweisung erstellen. Das wäre IMHO auch ziemlich schräg.

Das man nicht diese ganzen unnötigen Indizes braucht ist doch gerade ein Vorteil von Python. Warum will man sich diese zusätzlichen Variablen und Indirektionen unbedingt antun wenn man nicht muss? Programmiersprache A mit aller Gewalt wie Sprache B behandeln zu wollen geht in den meisten Fällen schief. Lass Dich auf Python ein.

Du weist hier `j` übrigens schon wieder einen Wert zu der nie benutzt wird. Das kann man sich sparen.

`s` müsste man nur an einer Stelle mit 1 initialisieren wenn man es an der richtigen Stelle macht. Aber eigentlich ist `s` überflüssig, weil es auf sehr einfache Weise mit dem Wert von `j` zusammenhängt.
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,

ja, da hast du recht. Aber ich muss auf die einzelnen Elemente später zugreifen können. Aus der Matrix muss ich dann auf die einzelnen Elemente zugreifen können:
z.B.
x1 y1 z1
x2 y2 z2
x3 y3 z3
usw.

So steht das dann in der Matrix oder wo auch immer. Später muss ich dann
(x1-x2)^2+(x1-y2)^3 usw rechnen können, also jedes Element einzelnd muss
zugreifbar sein! Aus diesem Grund denke ich an diese doppelten Indizes als
Lösung, weil dann über eine Doppelschleife später zugegriffen wird mit

Code: Alles auswählen

for i in range ()
   for j in range ()
      matrix[i][j]

..
So ein Teil folgt später im Programm und muss sozusagen bedient werden mit dem Einlesen aus einem File.

detlef
BlackJack

@01detlef: Das man vielleicht irgendwann einmal auf einzelne Elemente über den Index zugreifen muss, ist doch aber kein Grund das auch an den Stellen zu machen wo man es eben nicht muss. Da hat Sirius3 den passenden Quelltext doch auch schon gezeigt. Mach Dir einfach mal klar was da passiert und was für eine Datenstruktur dabei entsteht. Wenn dir das so als Trockenübung nicht vollständig möglich ist, dann hör am besten auf darüber zu grübeln bis Du an einem Rechner sitzt und das einfach mal ausprobieren kannst. Schau Dir die Daten „live” in einer Python-Shell an.

Wenn das in ein `numpy`-Array gewandelt wird, besteht die Chance dass man auch dort um die Indizes herum kommt, denn wenn man diesen Datentyp wirklich sinnvoll nutzen möchte, vermeidet man Schleifen im Python-Code und versucht so weit wie möglich auszunutzen, dass Operationen auf den Arrays auf viele Elemente ”auf einmal” wirken.
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,

also das die Indizes vllt nicht sinnvoll sind, glaube ich dir alles, aber ich muss das so machen, das steht fest. Es folgt im späteren Programm eine Doppelschleife, um auf die Liste/Matrix zuzugreifen.
Der Quellcode ist mir schon klar, aber mein Problem ist, glaub ich, dass ich nicht weiss wie die Daten nun gespeichert werden? Wie sieht die Speicherstruktur aus? Es ist ja keine nx3-Matrix (die 3 für x,y,z). Aus diesem Grund weiss ich auch nicht, wie ich nun auf coordinates zugreifen kann. Ich suche auch schon die ganze Zeit nach Einführungen im Internet, die sowas erklären...

Code: Alles auswählen

coordinates = []
fid = open(dateiname)
for line in fid:
    line=line.split()
    if line and line[0].upper()=='GRID':
        coordinates.append(map(float,line[2:]))
fid.close()
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,

kann es sein, dass die Abspeicherung das Problem ist? Werden die Listen nicht immer so abgespeichert: [x1,y1,z1],[x2,y2,z2],usw.? Dann kann ich natürlich nicht mit matrix[2][1] ein Element finden, weil bei meinen Test immer gesgat wurde, dass er außerhalb vom Index ist.
So wäre es möglich...
[x1,y1,z1]
[x2,y2,z2]

Ist das mein Problem, dass die Daten hintereinander gespeichert werden? Kann man das umwandeln in meine gewollte Struktur, auch wenn es nicht sinnvoll ist?

detlef
BlackJack

@01detlef: Nochmal: Der Vorschlag von Sirius3 macht das was Du willst! Glaube es einfach bis Du es selber ausprobieren kannst.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

01detlef hat geschrieben: also das die Indizes vllt nicht sinnvoll sind, glaube ich dir alles, aber ich muss das so machen, das steht fest. Es folgt im späteren Programm eine Doppelschleife, um auf die Liste/Matrix zuzugreifen.
Hu? Da stecken aber einige Hämmer drin. Kommt es Dir nicht merkwürdig vor, dass Du eine Sache "machen musst", von der Du selber glaubst, dass die nicht sinnvoll ist? Genau das ist doch der Augenblick an dem man inne halten muss und noch einmal darüber nachdenken sollte, was man eigentlich erreichen will und wie es ggf. besser geht!

Aber insbesondere Satz Nummer zwei zeigt im Kontext des bereits geschriebenen Ignoranz und Unwillen, sich auf Vorschläge einzulassen. Wieso zu Teufel muss man an Stelle "A" Code auf eine Art schreiben, die man an Stelle "B" braucht? Das musst Du uns noch mal erklären :twisted:

Ach ja, den Hinweis zum Dateihandling hast Du auch noch nicht umgesetzt ;-)

Kurz noch der (vermutlich bereits mehrfach geäußerte) Hinweis zum Posten von Quellcode: Wir haben hier spezielle Python-Code-Tags; die sorgen für Syntax Highlighting bei bekannten Sprachen.

[ code=python ] ... [ /code ] - ohne die Leerzeichen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
01detlef
User
Beiträge: 105
Registriert: Montag 10. Mai 2010, 21:59

Hallo,

also ich MUSS das nicht machen, aber es erspart eine Menge Arbeit, wenn ich das so mache. Dadurch kann der restliche Code unverändert benutzt werden.

Code: Alles auswählen

coordinates = []
fid = open(dateiname)
for line in fid:
    line=line.split()
    if line and line[0].upper()=='GRID':
        coordinates.append(map(float,line[2:]))
fid.close()
Wenn das alles so passt, dann könnte ich doch zum Umwandeln der Liste in eine Matrix folgendes machen (Es geht nur ums Verständnis, nicht nach Sinn urteilend)

Code: Alles auswählen

mat=nump.array(coordinates)
Ist das wenigstens richtig?

detlef
BlackJack

@01detlef: Ja das ist richtig.

Dann stellt sich allerdings die Frage ob man die nachfolgenden Rechnungen nicht auch mit `numpy`-Mitteln anstellen kann, also Python-Schleifen und damit Lauf-Indizes vermeiden, und Operationen auf ganze Arrays anwenden. Dazu ist `numpy` schliesslich gedacht.
Antworten