Da sonst keiner will, zeige ich vielleicht doch mal, was ich da zusammengefummelt habe; ich nehme an, dass
es an einigen Stellen etwas umständlich und unflexibel. Und: Was nimmt man am besten als "Strafwert" für
fehlende Indices?
(basierend auf BlackJacks Vorschlägen)
Code: Alles auswählen
#!/usr/bin/python3
import re
from collections import Counter, deque
from itertools import chain, tee, groupby
from operator import itemgetter
WORD_RE = re.compile(r'\w+')
class Text:
def __init__(self, name, content, n_lower=2, n_upper=5):
self.name = name
self.content = content
self.profile = Counter()
for n in range(n_lower, n_upper+1):
self.profile.update(Counter(iter_ngrams_from_text(self.content, n)))
def iter_words(text):
return (m.group(0) for m in WORD_RE.finditer(text))
def iter_ngrams(word, n):
ngram = deque('_' * n, n)
for character in chain(word.upper(), '_' * (n - 1)):
ngram.append(character)
yield ''.join(ngram)
def iter_ngrams_from_text(text, n):
return chain.from_iterable(map(lambda x:iter_ngrams(x, n), iter_words(text)))
def count_different(iterable, start=1, key=None):
for i, item in enumerate(groupby(iterable, key=key), start):
for value in item[1]:
yield value, i
def out_of_place_index(item, reference, missing=100):
reference_tmp = {i[0]:j for i, j in count_different(reference, key=itemgetter(1))}
index = 0
for element in count_different(item, key=itemgetter(1)):
key, rank = element[0][0], element[1]
try:
index += abs(rank - reference_tmp[key])
except KeyError:
index += missing
return index
def get_best_category(item, categories):
result = []
for category in categories:
result.append((out_of_place_index(item.profile.most_common(), category.profile.most_common()), category.name))
return min(result)
def main():
text = Text("Deutsch", "Alle Menschen sind frei und gleich an Würde und Rechten geboren Sie sind mit Vernunft und Gewissen begabt und sollen einander im Geist der Brüderlichkeit begegnen")
categories = [
Text("Englisch", "All human beings are born free and equal in dignity and rights They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood"),
Text("Dänisch", "Alle mennesker er født frie og lige i værdighed og rettigheder De er udstyret med fornuft og samvittighed, og de bør handle mod hverandre i en broderskabets ånd"),
Text("Norwegisch", "Alle mennesker er født frie og med samme menneskeverd og menneskerettigheter De er utstyrt med fornuft og samvittighet og bør handle mot hverandre i brorskapets ånd")
]
print(get_best_category(text, categories))
if __name__ == '__main__':
main()
Letztendlich hängt es aber davon ab, wie du's in deine Software einbauen willst. Im Prinzip hält man ja verschiedene N-Gramm-Profile, die anhand von Testkorpora gewonnen wurden, für die Kategorie vor und vergleicht dann. So kurze Textausschnitte wie hier sind natürlich sehr unzureichend.