Skip to content

Instantly share code, notes, and snippets.

@hinnerk
Created January 7, 2014 19:33
Show Gist options
  • Save hinnerk/8305396 to your computer and use it in GitHub Desktop.
Save hinnerk/8305396 to your computer and use it in GitHub Desktop.
n-gram Zerlegung aus einem Programmierkurs für Erwachsene aus dem Jahre 2010.
#!/usr/bin/env python2.7
from operator import itemgetter
import sys, pickle, os
def normalisiere_text(text):
"""
1. Buchstaben sollen zu Kleinbuchstaben werden
2. Nicht-Buchstabn sollen entfernt werden
>>> normalisiere_text("tesTtest123test")
'testtesttest'
"""
normalisierter_text = ""
buchstaben = "abcdefghijklmnopqrstuvwxyz"
for x in text:
x = x.lower()
if x in buchstaben:
normalisierter_text += x
return normalisierter_text
def zerlege_text(text):
""" zerlegt text in 5-gramme
>>> zerlege_text("testestestestestes")
['teste', 'estes', 'stest', 'teste', 'estes', 'stest', 'teste', 'estes', 'stest', 'teste', 'estes', 'stest', 'teste', 'estes', 'stes', 'tes', 'es', 's']
"""
ngramme = []
textumfang = len(text)
for pos in range(textumfang):
ngram = text[pos:pos+3]
if len(ngram) == 3:
ngramme.append(ngram)
return ngramme
def zaehle_ngramme(ngramme):
""" zahle ngramme in einer liste
>>> zaehle_ngramme(["test","test","tset"])
{'test': 2, 'tset': 1}
"""
zaehler = {}
for ngramm in ngramme:
zaehler[ngramm] = zaehler.get(ngramm, 0) + 1
return zaehler
def sortiere_ngramme(gezaehlte_ngramme):
""" ein dictionary {ngramm: 23} wird umgeformt
und als sortierte Liste zurueckgegeben
>>> sortiere_ngramme({'tset': 1, 'test': 2})
[('test', 2), ('tset', 1)]
"""
ngramm_liste = [(x, gezaehlte_ngramme[x]) for x in gezaehlte_ngramme]
# Schwartzian transformation
ngramm_liste.sort(key=itemgetter(1), reverse=True)
return ngramm_liste
def liste_ngramme(ngramm_liste, num):
""" gibt liste mit num haeufigsten
n-grammen zurueck
>>> liste_ngramme([('test',2),('tset',1)],1)
['test']
"""
return [x[0] for x in ngramm_liste[0:num]]
def datei_zu_ngramm(datei, anzahl_ngramme):
""" datei wird gelesen, in ngramme zerlegt
und eine liste der haeufigsten ngramme
wird zurueckgegeben
>>> datei_zu_ngramm("doctest.txt", 2)
['ester', 'teste']
"""
f = open(datei)
rohtext = f.read()
text = normalisiere_text(rohtext)
ngramme = zerlege_text(text)
gezaehlt = zaehle_ngramme(ngramme)
sortiert = sortiere_ngramme(gezaehlt)
return liste_ngramme(num=anzahl_ngramme, ngramm_liste=sortiert)
def vergleiche_dateien(datei, ngramme, anzahl_ngramme, vergleich):
""" vergleicht die haeufigsten ngramme
zweiter dateien
>>> vergleiche_dateien("deutsch1.txt", ['nicht', 'ianne'], 2, 2)
True
>>> vergleiche_dateien("deutsch1.txt", ["teste", "blabl"], 2, 2)
False
"""
ngramme_neu = datei_zu_ngramm(datei, anzahl_ngramme)
s1 = set(ngramme_neu)
s2 = set(ngramme)
return len(s1.intersection(s2)) >= vergleich
def lernen(datei, sprache):
"""
speichert daten sprachabhaengig auf festplatte
>>> lernen("deutsch1.txt", "deutsch")
>>> os.path.isfile("sprachen.dat")
True
"""
sprachen = {}
# daten aus datei laden, wen datei existiert
if os.path.isfile("sprachen.dat"):
sprachen.update(pickle.load(open("sprachen.dat")))
# 50 ngramme pro sprache werden gespeichert
ngramme = datei_zu_ngramm(datei, 50)
# ueberschreibt gelernte daten fuer diese sprache
sprachen[sprache] = ngramme
pickle.dump(sprachen, open("sprachen.dat", "wb"))
def vergleiche(datei):
""" vergleiche datei mit gespeicherten daten
# doctest hier einfuegen
"""
gelernt = pickle.load(open("sprachen.dat"))
sprachen = []
for sprache in gelernt:
if vergleiche_dateien(datei, gelernt[sprache], 50, 10):
sprachen.append(sprache)
return sprachen
def main():
"""
zwei dateien (als kommandozeilenoption) auswerten
"""
if sys.argv[1] == "lerne":
lernen(sys.argv[3], sys.argv[2])
elif len(sys.argv) == 2:
sprachen = vergleiche(sys.argv[1])
if len(sprachen) == 0:
print "Unbekannte Sprache"
else:
print "Text koennte sein: %s" % " ,".join(sprachen)
else:
print "lernen: %s lerne <dateiname>" % sys.argv[0]
print "vergleich: %s dateiname" % sys.argv[0]
if __name__ == "__main__":
# unsere Funktion
main()
# our doctest
#import doctest
#doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment