Dictionary

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
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Hallo miteinander,

ich habe eine Textdokument der Form:

Wort <Leerzeichen> Wort <Tab> Zahl
also zum Beispiel:
Hallo du 1
Hey du 2
Viel Spass 1
....

Dieses möchte ich dann in einem verschachtelten Dictionary speichern, da dies die geeignetste Form ist für die Weiterverarbeitung.
Allerdings habe ich bei der Initialisierung ein Problem:

Code: Alles auswählen

verschachtelt = defaultdict(lambda: defaultdict(int))
defaultdict sei nicht definiert. Ist die Zeile hier falsch, oder habe ich vergessen, noch etwas zu importieren?

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

``defaultdict`` befindet sich im Modul ``collections`` :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Ah klar :D
Danke!

Jetzt habe ich nur noch ein Problem:
Wie kann ich die Zeilen klug im Dictionary speichern?

Sei 'datei' die eingelesene Datei, dann habe ich das gemacht:

Code: Alles auswählen

for line in datei:
  verschachtelt[line] = line
datei.close()
print verschachtelt
Aber so ist die Ausgabe alles andere als gewünscht...
Ich muss das irgendwie berücksichtigen, dass zuerst Wort1, dann Wort2 und dann mit einem Tab abgetrennt deren Häufigkeit kommt..

Vielen Dank für die Hilfe, Marcel
BlackJack

@MarcelF6: Dann musst Du die Zeile wohl offensichtlich in ihre Bestandteile auftrennen. Und den letzten Teil in eine Zahl umwandeln.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Oke, das könnte man eigentlich so machen:

Code: Alles auswählen

for line in datei:
  verschachtelt['word1', 'word2', 'value'] = line.split()
datei.close()
Aber: Gibt es keine bessere Methode?
Ich möchte nachher eben das verschachtelte Dict 'verschachtelt' so aufrufen (um Wahrscheinlichkeiten auszurechnen):

Code: Alles auswählen

verschachtelt['wort1'].values()
Deshalb ist es nicht ideal, das Dict so zu speichern wie ich es hier mache.

Danke für die Hilfe.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du solltest dann nicht alles in den Schlüssel packen, dein Ansatz mit den Verschachtelten Dictionaries war doch schon gar nicht schlecht. Suchst du vielleicht einfach so etwas:

Code: Alles auswählen

>>> import collections
>>> data = [("a", "b", 1), ("a", "c", 2), ("b", "d", 3)]
>>> d = collections.defaultdict(lambda:collections.defaultdict(int))
>>> for first, second, value in data:
...     d[first][second] += value
... 
>>> d
defaultdict(<function <lambda> at 0x7f544d86e230>, {'a': defaultdict(<type 'int'>, {'c': 2, 'b': 1}), 'b': defaultdict(<type 'int'>, {'d': 3})})
Das Leben ist wie ein Tennisball.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Danke für die schnelle Antwort und die Hinweise!

Ich habs nun mit deinem Vorschlag probiert - der zwar sehr gut nachvollziehbar ist, aber "ValueError: too many values to unpack."

Code: Alles auswählen

import collections

datei = open('text.txt', 'r')
verschachtelt = collections.defaultdict(lambda: collections.defaultdict(int))

for wort1, wort2, value in datei:
  verschachtelt[wort1][wort2] += value
datei.close()
Ich weiss nicht genau, woran das liegt. Die einzige Fehlerquelle könnte am Text-Dokument liegen, aber:
text.txt ist von der Form:
*wort1* <Leerzeichen> *wort2* <Tab> *eine Zahl*
Also fällt diese Fehlerquelle eigentlich weg.
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

MarcelF6 hat geschrieben:

Code: Alles auswählen

for wort1, wort2, value in datei:
Dir scheint es erheblich an Grundlagenwissen zu mangeln. Das Beste wäre, wenn du mal das offizielle Python-Tutorial durcharbeitest. Hier wird jedenfalls nicht auf magische Weise erkannt, dass an Leerzeichen (bzw Whitespace) gesplittet werden soll. Was du willst, ist wohl eher sowas hier:

Code: Alles auswählen

for zeile in datei:
    wort1, wort2, wort3 = zeile.split()
Aber nochmal: Es ist wirklich zielführender, wenn du dich in den nächsten Wochen (sofern du Zeit dafür hast) ganz in Ruhe mit den Grundlagen von Python befasst und dann deine Fragen auch auf "höherem Niveau" stellen kannst.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Danke für die Rückmeldung.
Eigentlich bin ich tatsächlich am Tutorial dran, aber halt noch nicht bei dem Thema.

Ich habe einfach noch eine Frage: Bei verschachtelten Dict. gibt es ja die Funktion .values(). Wieso aber kann ich die nicht anwenden?

Zum Beispiel:

Code: Alles auswählen

import collections

datei = open('text.txt', 'r')
verschachtelt = collections.defaultdict(lambda:collections.defaultdict(int))

for zeile in datei:
  wort1, wort2, value = zeile.split()
  verschachtelt[wort1][wort2] = wort1, wort2, value
datei.close()

if __name__== "__main__":
  print verschachtelt['Act'].values()
Die Ausgabe ist dann von der Art: ('Act', 'hath', '1').
Was ich aber "erwarte" wäre nur die 1.
Was muss hierzu geändert werden?
BlackJack

@MarcelF6: Du weist ein Tupel mit drei Werten zu, erwartest jetzt aber ernsthaft das tatsächlich nur der dritte Wert im Tupel gespeichert wird!? Die anderen soll Python einfach auf magische Weise „vergessen” weil Dir das so in den Kram passen würde? Das bekommt Python wie genau heraus? Durch Gedanken lesen?

Code: Alles auswählen

In [3]: spam = 'a', 'b', 42

In [4]: print spam
('a', 'b', 42)
Hier würdest Du jetzt tatsächlich erwarten, dass nur die 42 von der ``print``-Anweisung ausgegeben wird!?

Du musst schon selber lernen wie Python funktioniert und dieses Wissen dann anwenden und nicht irgendetwas hinschreiben und hoffen und wünschen, dass es das tut was Du möchtest. So funktioniert Programmieren nicht.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Hallo.
Ich habe mir natürlich etwas mehr überlegt, als du hier darstellst.
Ich bin nicht sicher, ob du mich für dumm verkaufen willst. Wie auch immer...deine Nachricht hat mir nicht allzu viel gebracht, da sie so ziemlich an meinem Problem vorbeischiesst.

Meine Elemente im verschachtelten Dict sind Strings, und um die jeweilige Häufigkeit eines Wortes zu erhalten, muss ich auf die jeweils dritte Spalte zugreifen, diese Zahl in einen Int umwandeln und sie dann addieren.
Dazu habe ich folgendes geschrieben:

Code: Alles auswählen

  datei = open('text.txt', 'r')
  total = 0
  for wort in datei:
    for i in str(verschachtelt['Act'][wort][2]):
      total = total + int(i)
  datei.close()
  print total
Das funktioniert allerdings nicht, weil int-Objekte eben nicht 'subscriptable' sind.

Da diese Problematik nicht in dem Tutorial behandelt wird, das ich gerade lese, dachte ich, man könne mir evtl. hier helfen...

Edit: 'Act' ist hier einfach ein Beispiel. Es soll also die Summe der Häufigkeiten ausgegeben werden, wobei 'Act' plus ein anderes Wort vorkommt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Zerlege doch einfach mal deinen Code in viele kleine Einzelanweisungen und gibt die Werte der Zwischenschritte mittels print aus. Dann findest du relativ leicht raus, wo bei dir das Problem liegt.

BlackJacks Beitrag geht auch nicht an deinem Problem vorbei, er zeigt genau den Fehler auf den du machst.
Das Leben ist wie ein Tennisball.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Ok, habs kapiert :D
Ich Idiot hab immer die ganzen Zeilen übergeben, statt value einzeln :)
Danke euch allen!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Und um noch kurz auf deinen Code einzugehen: Schaue dir mal das with-Statement an, damit werden Dateien automtisch geschlossen, auch im Fehlerfall. Aus

Code: Alles auswählen

fp = open("datei")
print fp.read()
fp.close()
wird dann

Code: Alles auswählen

with open("datei") as fp:
    print fp.read()
Du sparst dir damit das explizite close und sorgst gleichzeitig für ein korrektes Handling der Dateien.
Das Leben ist wie ein Tennisball.
Antworten