Python-Anfänger braucht Hilfe bei multiplen Datenstrukturen
Hallo!
Hier mal eine einfache Lösung. Die Verwendung der default_dicts find ich ja doch eher kryptisch...
Du müsstest noch das Lesen des strings duch das Lesen der Datei ersetzen. Aber da weißt du ja wie das geht.
lexicon hat am Ende folgenden Inhalt:
Ich hoffe das ist das was du dir vorgestellt hast.
Frohe Weihnachten
HerrHagen
Hier mal eine einfache Lösung. Die Verwendung der default_dicts find ich ja doch eher kryptisch...
Du müsstest noch das Lesen des strings duch das Lesen der Datei ersetzen. Aber da weißt du ja wie das geht.
Code: Alles auswählen
dat = """The AT
Fulton NP
County NN
an AT
an AT
an AT
an NN
an IN
investigation NN
investigation XXX
investigation NN
of IN
Atlanta's NP$
recent JJ
primary NN
election NN
produced VBD """
lines = dat.splitlines() # ersetzen durch Lesen aus Datei
lines = map(str.split, lines)
lexicon = {}
for word, tag in lines:
if not lexicon.has_key(word):
lexicon[word] = {tag:1}
else:
try:
lexicon[word][tag] += 1
except:
lexicon[word][tag] = 1
Code: Alles auswählen
>>> lexicon
{'produced': {'VBD': 1}, 'of': {'IN': 1}, "Atlanta's": {'NP$': 1}, 'primary': {'NN': 1}, 'an': {'AT': 3, 'NN': 1, 'IN': 1}, 'County': {'NN': 1}, 'investigation': {'XXX': 1, 'NN': 2}, 'election': {'NN': 1}, 'The': {'AT': 1}, 'Fulton': {'NP': 1}, 'recent': {'JJ': 1}}
>>> for a, b in zip(lexicon.keys(), lexicon.values()):
print a, b
produced {'VBD': 1}
of {'IN': 1}
Atlanta's {'NP$': 1}
primary {'NN': 1}
an {'AT': 3, 'NN': 1, 'IN': 1}
County {'NN': 1}
investigation {'XXX': 1, 'NN': 2}
election {'NN': 1}
The {'AT': 1}
Fulton {'NP': 1}
recent {'JJ': 1}
Frohe Weihnachten
HerrHagen
@HerrHagen: Also ich finde `defaultdict`\s weit weniger kryptisch als Deine Lösung, wo man sich erst einmal klar machen muss welcher Zweig wann zum Einsatz kommt, oder so eine lange Zeile mit zwei `get()`-Aufrufen.
Alternative zu ``lambda`` wäre `functools.partial()`:
Ansonsten würde ich ``in`` statt `has_key()` verwenden und auf keinen Fall ein ``except`` ohne eine konkrete Ausnahme verwenden. Zeile 30 soll ja zum Beispiel nicht ausgeführt werden, wenn in Zeile 28 ein Fipptehler bei einem Namen existiert, oder wenn jemand bei der Programmausführung an einer ungünstigen Stelle Strg+C drückt.
Alternative zu ``lambda`` wäre `functools.partial()`:
Code: Alles auswählen
from __future__ import division, with_statement
from collections import defaultdict
from functools import partial
from pprint import pprint
def main():
lexicon = defaultdict(partial(defaultdict, int))
with open('test.txt') as lines:
for line in lines:
word, tag = line.rstrip().split()
lexicon[word][tag] += 1
for word, tags in sorted(lexicon.iteritems()):
print '%s: %s' % (word, sorted(tags.iteritems()))
if __name__ == "__main__":
main()
Da hast du natürlich recht, war einfach schon etwas spät in der Nacht...Ansonsten würde ich ``in`` statt `has_key()` verwenden und auf keinen Fall ein ``except`` ohne eine konkrete Ausnahme verwenden. Zeile 30 soll ja zum Beispiel nicht ausgeführt werden, wenn in Zeile 28 ein Fipptehler bei einem Namen existiert, oder wenn jemand bei der Programmausführung an einer ungünstigen Stelle Strg+C drückt.
Da bin ich anderer Meinung. Deine Variante ist wirklich nett. Hat aber meiner Meinung nach ein Problem:@HerrHagen: Also ich finde `defaultdict`\s weit weniger kryptisch als Deine Lösung, wo man sich erst einmal klar machen muss welcher Zweig wann zum Einsatz kommt, oder so eine lange Zeile mit zwei `get()`-Aufrufen.
Code: Alles auswählen
from collections import defaultdict
from functools import partial
Außerdem find ich die Verzweigung nicht so schlimm, da sich das ganze wie Pseudocode ließt. Wenn lexicon nicht word enthält, dann lege einen neuen Eintrag...
Ich finde, dass man bei der defaultdict Variante mehr nachdenken muss warum das ganze überhaupt funktioniert.
Warum importierst du pprint, division wenn du sie dann nicht benutzt?
MFG HerrHagen
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Wieso? Eine Einsteigerlösung bedeutet ja nicht dass man alles auf umständliche Weise machen muss. Der Einsatz von ``partial`` ist da etwas Grenzwertig, da für Anfänger Funktionen höherer Ordnung etwas tricky sein können (außer sie haben Higher Order Perl gelesen, was es jetzt kostenlos online gibt), aber das ``defaultdict`` macht den Code ausreichend simpler dass es sich lohnt einfach mal in die Doku zu schauen was es tut. Einsteigercode ist ja auch für den Einstieg gedacht aber das heißt ja nicht dass man an dem Code nicht wachsen kann.HerrHagen hat geschrieben:Da bin ich anderer Meinung. Deine Variante ist wirklich nett. Hat aber meiner Meinung nach ein Problem:Man benötigt die Kenntnis der Funktionsweise von gleich zwei Standard-Modulen. Das ist ja nichts schlimmes, ist aber als Einsteigerlösung (nach der hier gefragt wurde) eher weniger zu gebrauchen.Code: Alles auswählen
from collections import defaultdict from functools import partial
Einige Leute haben halt Templates für neue Python-Dateien und da kann es dann vorkommen, dass da ``pprint`` oder ``division`` automatisch importiert werden. Für den Quelltext ist es natürlich unnötig.HerrHagen hat geschrieben:Warum importierst du pprint, division wenn du sie dann nicht benutzt?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Der `__future__`-Import ist bei mir Standard. `pprint` dagegen überflüssigerweise noch drin geblieben.
@ Herr Hagen
vielen Dank, das ist genau das, was ich gesucht habe. Eigentlich total simpel, aber man muss erst mal drauf kommen. Wer wie ich so lange in Perl programmiert hat, hat es mit Python erst mal etwas schwer.
Ich bedanke mich recht herzlich und wünsche euch noch schöne Feiertage.
Dingels
vielen Dank, das ist genau das, was ich gesucht habe. Eigentlich total simpel, aber man muss erst mal drauf kommen. Wer wie ich so lange in Perl programmiert hat, hat es mit Python erst mal etwas schwer.
Ich bedanke mich recht herzlich und wünsche euch noch schöne Feiertage.
Dingels
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Wobei der Code recht ineffizient ist, da dort erst die ganze Datei in den Speicher gelesen wird und dan gesplittet - würde man vermeiden wollen wenn es auch anders geht. Und in diesem Beispiel ist das ganz einfach möglich, indem man über die Zeilen der Datei direkt iteriert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Das meinte ich eigentlich nicht, sondern dass da ``splitlines()`` auf einem String ausgeführt wird was dann recht viel Zeit und Speicher beansprucht wenn man auch direkt über eine Datei iterieren kann.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Und vielleicht noch der Hinweis, dass man sich in Python eigene Klassen schreiben könnte, wenn es viele Funktionen gibt, die auf der gleichen Art von verschachtelter Datenstruktur operieren.
Spätestens ab der dritten Verschachtelungsebene in der Datenstruktur ist das IMHO ein muss das aufzubrechen, damit der Quelltext verständlich und wartbar bleibt.
Spätestens ab der dritten Verschachtelungsebene in der Datenstruktur ist das IMHO ein muss das aufzubrechen, damit der Quelltext verständlich und wartbar bleibt.