Aus einer Liste ein verschachteltes Dict erstellen

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
Mary86
User
Beiträge: 9
Registriert: Donnerstag 24. März 2011, 14:29

Donnerstag 24. März 2011, 14:38

Hallo!
Ich bin absoluter Python-Neuling und quäl mich schon geraume Zeit mit folgendem Problem.
Ich habe eine Datei aus der ich ein Dictionary erstellen soll auf dass man dann zugreifen kann und dem Benutzer wird dann einen Summe ausgegeben.
Im Prinzip nicht schwer aber ich bekomm das mit dem verschachtelten Dict einfach nicht hin!
Also wenn ich die Liste mit:

Code: Alles auswählen

for line in pM.readlines():
  line = line.rstrip()
  data = line.split(',')
  print(data)
einlese bekomm ich im Terminal das:
['Element', 'Isotope', 'Monoisotopic mass', 'Natural abundance']
['C', '12', '12.0', '0.9893']
['C', '13', '13.0033548378', '0.0107']
['C', '14', '14.003241988', '0.0']
['H', '1', '1.0078250321', '0.999885']
['H', '2', '2.014101778', '0.000115']
['H', '3', '3.0160492675', '0.0']
['N', '14', '14.0030740052', '0.99632']
['N', '15', '15.0001088984', '0.00368']
['O', '16', '15.9949146221', '0.99757']
['O', '17', '16.9991315', '0.00038']
['O', '18', '17.9991604', '0.00205']
['S', '32', '31.97207069', '0.9493']
['S', '33', '32.9714585', '0.0076']
['S', '34', '33.96786683', '0.0429']
['S', '36', '35.96708088', '0.0002']
Und nun ist mein Ziel dass ich folgendes Dict bekomme:
{'C':{12,13,14},'H':{1,2,3,}........}
Wenn ich das damit versuch:

Code: Alles auswählen

 if data[0] not in pMDict:
    pMDict [data[0]] = {data[1]}
  elif data[0] in pMDict:
    pMDict [data[0]] = {data[1]}
print (pMDict)
überschreibt er mir natürlich jeden Eintrag.
Ich könnte natrülich über mehrere Schleifen verschiedene Dictionarys erstellen und die dann wieder zusammenfügen, aber das erscheint mir dann doch etwas zu umständlich.
Vielleich kannt mir ja jemand von euch helfen:
Bisher sieht das ganze Prog. so aus:

Code: Alles auswählen

import csv
import math

pM = open ("isotopes.csv") # öffnet die Datei mit den Atommassen
pMDict = {} #pM = physikalische Massen
zeile = []

for line in pM.readlines():
  line = line.rstrip()
  data = line.split(',')
  print(data)
  if data[0] not in pMDict:
    pMDict [data[0]] = {data[1]}
  elif data[0] in pMDict:
    pMDict [data[0]] = {data[1]}
print (pMDict)
Vielen Dank schon mal
Mary
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Donnerstag 24. März 2011, 14:54

Hallo und willkommen im Forum!

Mit einem defaultdict geht das eigentlich recht einfach:

Code: Alles auswählen

>>> from collections import defaultdict
>>> data=[['C', '12', '12.0', '0.9893'],
... ['C', '13', '13.0033548378', '0.0107'],
... ['C', '14', '14.003241988', '0.0'],
... ['H', '1', '1.0078250321', '0.999885'],
... ['H', '2', '2.014101778', '0.000115'],
... ['H', '3', '3.0160492675', '0.0'],
... ['N', '14', '14.0030740052', '0.99632'],
... ['N', '15', '15.0001088984', '0.00368']]
>>> d = defaultdict(list)
>>> for elem, n, _, _ in data:
...     d[elem].append(n)
... 
>>> d
defaultdict(<type 'list'>, {'H': ['1', '2', '3'], 'C': ['12', '13', '14'], 'N': ['14', '15']})
Das Leben ist wie ein Tennisball.
Mary86
User
Beiträge: 9
Registriert: Donnerstag 24. März 2011, 14:29

Montag 28. März 2011, 08:50

Hallo EyDu
Danke für deine schnelle Antwort, leider klappt das so irgendwie nicht.
Hab jetzt folgenden Code:

Code: Alles auswählen

import csv
import math
from collections import defaultdict

pM = open ("isotopes.csv") # öffnet die Datei mit den Atommassen
pMDict = defaultdict(list) #pM = physikalische Massen
zeile = []

for line in pM.readlines():
  line = line.rstrip()
  data = line.split(',')
  print(data)
  for element, n, _, _ in data:
    pMDict[element].append(n)
  
print (pMDict)
Und im Terminal gibt er mir dann folgenden Fehler aus:
['Element', 'Isotope', 'Monoisotopic mass', 'Natural abundance']
Traceback (most recent call last):
File "./Chemie2.py", line 15, in <module>
for element, n, _, _ in data:
ValueError: too many values to unpack

Und wenn ich den Code änder so dass die zweite Schleife nicht in der ersten ist kommt das:
['Element', 'Isotope', 'Monoisotopic mass', 'Natural abundance']
['C', '12', '12.0', '0.9893']
['C', '13', '13.0033548378', '0.0107']
['C', '14', '14.003241988', '0.0']
['H', '1', '1.0078250321', '0.999885']
['H', '2', '2.014101778', '0.000115']
['H', '3', '3.0160492675', '0.0']
['N', '14', '14.0030740052', '0.99632']
['N', '15', '15.0001088984', '0.00368']
['O', '16', '15.9949146221', '0.99757']
['O', '17', '16.9991315', '0.00038']
['O', '18', '17.9991604', '0.00205']
['S', '32', '31.97207069', '0.9493']
['S', '33', '32.9714585', '0.0076']
['S', '34', '33.96786683', '0.0429']
['S', '36', '35.96708088', '0.0002']
Traceback (most recent call last):
File "./Chemie2.py", line 15, in <module>
for element, n, _, _ in data:
ValueError: need more than 1 value to unpack

Gruß Mary
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Montag 28. März 2011, 10:43

Hallo.

Das liegt wahrscheinlich an einer leeren Zeile in der Datei. Prüfe einfach vor dem ausführen der inneren Schleife, ob tatsächlich vier Elemente in data vorhanden sind. Du solltest dateien übrigens mittels des with-Statements öffnen, dann werden diese auch wieder geschlossen. Weiter ist das readlines() überflüssig, du kannst direkt über pM iterieren:

Code: Alles auswählen

with open("isotipes.csv") as pM:
    for lin in pM:
        ...
Warum benutzt du eigentlich nicht das csv-Modul? Immerhin bindest du es auch ein. Dann erledigt sich das Problem von alleine.

Sebastian
Das Leben ist wie ein Tennisball.
Mary86
User
Beiträge: 9
Registriert: Donnerstag 24. März 2011, 14:29

Montag 28. März 2011, 10:51

Hallo Sebastian!
Naja, eigentlich wollte ich das auch mit csv machen, aber ich weiß nicht wie das geht :-(
Ähm es sind tatsächlich immer 4 einträge in Data... aber es geht immer noch nicht...
Viele Grüße
Mary
Mary86
User
Beiträge: 9
Registriert: Donnerstag 24. März 2011, 14:29

Montag 28. März 2011, 10:59

Hi,
hab es jetzt nochmal so versucht:

Code: Alles auswählen

import csv
import math
from collections import defaultdict


pMDict = defaultdict(list) #pM = physikalische Massen
zeile = []

with open ("isotopes.csv") as pM:
  for line in pM:
    line = line.rstrip()
    data = line.split(',')
    print(data)
    print(len(data))
    for element, n, _, _ in data:
      pMDict[element].append(n)
  
print (pMDict)
Trotzdem sagt er im Terminal wieder:
['Element', 'Isotope', 'Monoisotopic mass', 'Natural abundance']
4
Traceback (most recent call last):
File "./chemie3.py", line 17, in <module>
for element, n, _, _ in data:
ValueError: too many values to unpack

Aber es sind in jeder Zeile 4 Elemente...
Gruß
Mary
BlackJack

Montag 28. März 2011, 11:03

@Mary86: Dann überleg doch mal worüber die Schleife iteriert und was dann da bei jedem Durchlauf versucht wird an die vier Namen zu "entpacken". Wenn Du durch überlegen nicht drauf kommst, kannst Du das entpacken ja mal in die Schleife hinein ziehen und die einzelnen Elemente vorher mit ``print`` ausgeben.
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Montag 28. März 2011, 11:06

Hallo.

Ach, na klar: Du darfst nicht über data iterieren. Noch zu früh ^^

Code: Alles auswählen

element, n = data[:2]
pMDict[element].append(n)
sollte statt der for-Schleife gehen.

Sebastian
Das Leben ist wie ein Tennisball.
Mary86
User
Beiträge: 9
Registriert: Donnerstag 24. März 2011, 14:29

Montag 28. März 2011, 11:11

Super danke, jetzt funzt es :-)
Ähm zum csv hatte das so versucht:

Code: Alles auswählen

import csv
import math

pM = csv.DictReader(open("isotopes.csv", "rb")) 
for row in pM:
  print(row)


Und da hat er mir dann immer sowas ausgespuckt:
Traceback (most recent call last):
File "./chemie4.py", line 9, in <module>
for row in pM:
File "/usr/lib/python3.1/csv.py", line 99, in __next__
self.fieldnames
File "/usr/lib/python3.1/csv.py", line 86, in fieldnames
self._fieldnames = next(self.reader)
_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

Deswegen hab ich dann nicht mehr weiter damit gearbeitet... weil ich davon noch weniger Ahnung hab als von Dicts, und Schleifen *g*
Grüße
und danke!
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Montag 28. März 2011, 11:21

Die Fehlermeldung sagt doch schon, wo das Problem liegt: Du hast die Datei im Binaermodus geoeffnet, obwohl CSV-Dateien reine Textdateien sind.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Mary86
User
Beiträge: 9
Registriert: Donnerstag 24. März 2011, 14:29

Montag 28. März 2011, 13:33

Hallo Rebecca!
Danke für deine schnelle Antwort, aber da ich auch nicht weiß wie ich die im Textmodus öffne ... *g* und das sind Fragen die gehören hier bestimmt nicht rein, weil man sich die ganz leicht anlesen kann *g*
Das Programm funktioniert jetzt auch auch zum Glück so!
Nur mit dem math-modul muss ich mich jetzt noch etwas näher beschäftigen, damit ich die Sachen auch verrechnen kann.
Bisher hab ich rausgefunden wie ich die Werte in eine Liste addiere... nun soll der mir aber nicht alle Werte addieren sondern teilweise einen Wert einfach doppelt... naja
Aber danke euch beiden für die Hilfe!
Gruß
Mary
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Montag 28. März 2011, 13:40

Überlege doch einmal, was das "b" in "rb" beim Öffnen einer Datei bedeuten könnte ;-)
Das Leben ist wie ein Tennisball.
Antworten