Python-Skript Update und Fix.
[wortliste.git] / skripte / python / abgleich_neueintraege.py
blob72a22b1361db6d16a33e5ac90a9655ec1c7fe62b
1 #!/usr/bin/env python
2 # -*- coding: utf8 -*-
3 # :Copyright: © 2011 Günter Milde.
4 # Released without warranty under the terms of the
5 # GNU General Public License (v. 2 or later)
6 # :Id: $Id: $
8 # Versuche Trennstellen neuer Wörter aus vorhandenen zu ermitteln
9 # ===============================================================
11 # Übertragen von kategorisierten Trennstellen vorhandener Wörter
12 # auf neu aufzunehmende, ungetrennte Wörter.
14 # Erwartet eine Datei mit 1 Wort/Zeile.
15 # Pfad/Dateiname im Abschnitt Konfiguration anpassen!
17 # Schreibt eine Liste von Einträgen für die Wörter, welche durch Abgleich
18 # mit der Datenbasis getrennt werden konnten auf stdout.
20 # Die Liste kann nach ``neu.todo`` gespeichert und (nach Durchsicht) mit
21 # ``prepare_patch.py neu`` in die Wortliste eingepflegt werden.
23 # ::
25 import sys, codecs
26 from collections import defaultdict # Wörterbuch mit Default
27 from werkzeug import WordFile, WordEntry, join_word, toggle_case, sortkey_duden
28 from expand_teilwoerter import expand_wordfile
30 # Konfiguration
31 # -------------
33 # Pfad zur Datei mit den neu einzutragenden Wörtern::
35 # neuwortdatei = "spell/zusatz-de-1996-aspell-compact"
36 neuwortdatei = "spell/dehyph-exptl-MV-KorrekturenA-Z.txt"
37 # neuwortdatei = "spell/DDR.txt"
39 # Vorhandene identische Einträge aus Neueinträgen aussortieren::
41 filtern = False
42 # filtern = True
44 # Trennmusterliste
46 wordfile = WordFile('../../wortliste')
49 # Funktionen
50 # -----------
52 # Übertrag von Praefixen auf Wörter ohne Präfix::
54 def praefixabgleich(key, praefix, grossklein=False):
56 if key.istitle():
57 praefix = praefix.title()
59 if not key.startswith(join_word(praefix)):
60 return ''
62 altkey = key[len(join_word(praefix)):]
64 if grossklein:
65 altkey = toggle_case(altkey)
67 try:
68 altentry = words[altkey]
69 except KeyError:
70 return ''
72 entry = WordEntry(key)
73 # print "fundum", key, unicode(entry)
74 for wort in altentry[1:]:
75 if not wort.startswith(u'-'):
76 wort = wort.lower()
77 wort = u'<'.join([praefix, wort])
78 entry.append(wort)
80 return entry
82 praefixe = [u'abo',
83 u'ab',
84 u'ab<zu',
85 u'auf<zu',
86 u'aus<zu',
87 u'ein<zu',
88 u'mit<zu',
89 u'um<zu',
90 u'un-ter<zu',
91 u'weg<zu',
92 u'aber',
93 u'ad',
94 u'aero',
95 u'af-ro',
96 u'ag-ro',
97 u'al-lergo',
98 u'al-lein',
99 u'all',
100 u'als',
101 u'am-bi',
102 u'ami-no',
103 u'an-dro',
104 u'an-gio',
105 u'an-thro-po',
106 u'an-ti',
107 u'ang-lo',
108 u'an',
109 u'apo',
110 u'ar-chaeo',
111 u'ar-che',
112 u'ar-chäo',
113 u'ar-terio',
114 u'ar-thro',
115 u'asyn',
116 u'at-mo',
117 u'au-ßer',
118 u'auf',
119 u'aus',
120 u'aus<zu',
121 u'aut',
122 u'ba-ro',
123 u'bak-te-rio',
124 u'be',
125 u'bei',
126 u'ben-zo',
127 u'bi-blio',
128 u'bio',
129 u'che-mo',
130 u'chi-ro',
131 u'chlo-ro',
132 u'cho-reo',
133 u'chro-mo',
134 u'chro-no',
135 u'cy-ano',
136 u'dar',
137 u'de-ka',
138 u'de-zi',
139 u'demo',
140 u'der-ma-to',
141 u'des',
142 u'di-cho',
143 u'di-no',
144 u'dia',
145 u'dis',
146 u'dis-ko',
147 u'down',
148 u'drein',
149 u'durch',
150 u'dys',
151 u'e-tho',
152 u'ego',
153 u'ein',
154 u'elek-tro',
155 u'em-por',
156 u'emp',
157 u'en-do',
158 u'en-te-ro',
159 u'ent',
160 u'epi',
161 u'er-go',
162 u'er',
163 u'es-chato',
164 u'eth-no',
165 u'ety-mo',
166 u'ext-ro',
167 u'ex',
168 u'fe-ro',
169 u'fem-to',
170 u'fer-ro',
171 u'fo-no',
172 u'fort',
173 u'fran-ko',
174 u'für',
175 u'ga-so',
176 u'ge-gen',
177 u'ge-no',
178 u'ge-ron-to',
179 u'geo',
180 u'ge',
181 u'gi-ga',
182 u'gi-gan-to',
183 u'go-no',
184 u'gra-fo',
185 u'gra-pho',
186 u'gy-nä-ko',
187 u'he-lio',
188 u'he-te-ro',
189 u'he-xa',
190 u'hek-to',
191 u'hekt',
192 u'hemi',
193 u'her',
194 u'hier',
195 u'hin',
196 u'hin-ter',
197 u'hint',
198 u'ho-lo',
199 u'ho-mo',
200 u'ho-möo',
201 u'hoch',
202 u'hy-dro',
203 u'hy-per',
204 u'hy-po',
205 u'hym-no',
206 u'hyp-no',
207 u'hä-ma-to',
208 u'hä-mo',
209 u'ideo',
210 u'idio',
211 u'iko-no',
212 u'il',
213 u'im',
214 u'im-mu-no',
215 u'in',
216 u'in-fra',
217 u'in-ter',
218 u'in-tra',
219 u'ins',
220 u'int-ro',
221 u'io-no',
222 u'kar-dio',
223 u'kar-to',
224 u'kata',
225 u'klep-to',
226 u'kli-no',
227 u'kon',
228 u'kon-tra',
229 u'kor-re',
230 u'kos-mo',
231 u'kri-mi-no',
232 u'kri-no',
233 u'kryp-to',
234 u'leu-ko',
235 u'leuk',
236 u'le-xi-ko',
237 u'li-tho',
238 u'lim-no',
239 u'lo-go',
240 u'los',
241 u'lym-pho',
242 u'ma-gne-to',
243 u'mak-ro',
244 u'mam-mo',
245 u'me-ga',
246 u'me-lo',
247 u'me-so',
248 u'me-ta',
249 u'me-teo-ro',
250 u'me-tho-do',
251 u'mik-ro',
252 u'mil-li',
253 u'miss',
254 u'mit',
255 u'mo-no',
256 u'mor-pho',
257 u'mu-si-ko',
258 u'mul-ti',
259 u'my-co',
260 u'my-tho',
261 u'na-no',
262 u'nach',
263 u'ne-ben',
264 u'neo',
265 u'neu-ro',
266 u'neur',
267 u'nie-der',
268 u'no-wo',
269 u'non',
270 u'nost',
271 u'ob',
272 u'oben',
273 u'ober',
274 u'off',
275 u'ohn',
276 u'oli-go',
277 u'olig',
278 u'om-ni',
279 u'on-ko',
280 u'on-to',
281 u'op-to',
282 u'or-tho',
283 u'oszil-lo',
284 u'out',
285 u'over',
286 u'oxy',
287 u'ozea-no',
288 u'pa-ra',
289 u'pa-tho',
290 u'pa-tri',
291 u'pan-to',
292 u'pe-re',
293 u'pen-ta',
294 u'pet-ro',
295 u'phar-ma',
296 u'phar-ma-ko',
297 u'phi-lo',
298 u'phil',
299 u'pho-no',
300 u'pho-to',
301 u'phra-seo',
302 u'phy-lo',
303 u'phy-sio',
304 u'phy-to',
305 u'phä-no',
306 u'pneu-mo',
307 u'po-eto',
308 u'po-li-to',
309 u'po-ly',
310 u'po-ten-tio',
311 u'pro-to',
312 u'prä',
313 u'pseud',
314 u'psy-cho',
315 u'py-ro',
316 u'pä-do',
317 u'päd',
318 u'raus',
319 u're',
320 u'rein',
321 u'ret-ro',
322 u'ri-bo',
323 u'rä-to',
324 u'rück',
325 u'sa-mo',
326 u'sak-ro',
327 u'se-mi',
328 u'seis-mo',
329 u'selb',
330 u'ser-bo',
331 u'si-no',
332 u'so',
333 u'so-zio',
334 u'sou',
335 u'spek-tro',
336 u'ste-no',
337 u'ste-reo',
338 u'ste-tho',
339 u'stra-to',
340 u'su-per',
341 u'sub',
342 u'sup-ra',
343 u'sus',
344 u'syn',
345 u'ta-xo',
346 u'tau-to',
347 u'te-leo',
348 u'te-ra',
349 u'tech-no',
350 u'tele',
351 u'telo',
352 u'ter-mi-no',
353 u'tet-ra',
354 u'ther-mo',
355 u'throm-bo',
356 u'to-mo',
357 u'to-po',
358 u'to-xi-ko',
359 u'tra-gi',
360 u'trans',
361 u'tro-po',
362 u'tur-bo',
363 u'ty-po',
364 u'ul-tra',
365 u'um',
366 u'un',
367 u'un-der',
368 u'un-ter',
369 u'uni',
370 u'ur',
371 u'uro',
372 u'ver',
373 u'vi-no',
374 u'vi-ro',
375 u'vib-ra',
376 u'voll',
377 u'von',
378 u'vor',
379 u'vorn',
380 u'vul-ka-no',
381 u'weg',
382 u'wi-der',
383 u'xe-no',
384 u'xy-lo',
385 u'zen-ti',
386 u'zen-tri',
387 u'zer',
388 u'zu',
389 u'zwie',
390 u'zy-klo',
391 u'zy-to',
392 u'ägyp-to',
393 u'öko',
394 u'über',
397 # Nach Länge sortieren, damit spezifischere zuerst Probiert werden:
398 praefixe.sort(key = len)
399 praefixe.reverse()
402 # Übertrag von Einträgen auf Wörter mit anderer Endung::
404 def endungsabgleich(key, alt, neu, grossklein=False):
406 if not key.endswith(join_word(neu)):
407 return ''
408 OK = True
409 altkey = key[:-len(join_word(neu))] + join_word(alt)
410 if grossklein:
411 altkey = toggle_case(altkey)
413 try:
414 altentry = words[altkey]
415 except KeyError:
416 return ''
418 entry = WordEntry(key)
419 # print "fundum", key, unicode(entry)
420 for wort in altentry[1:]:
421 if not wort.startswith(u'-'):
422 if alt:
423 wort = wort[:-len(alt)]
424 wort += neu
425 if grossklein:
426 wort = toggle_case(wort)
427 if join_word(wort) != key:
428 OK = False
429 entry.append(wort)
430 if OK is False:
431 print u"# Übertragungsproblem: %s -> %s (%s,%s) %s" % (
432 altkey, key, alt, neu, unicode(entry))
433 return ''
435 entry.regelaenderungen()
436 return entry
439 # Endungen
440 # --------
441 # ``(<alt>, <neu>)`` Paare von Endungen::
443 endungen = [
444 (u'', u'-de'),
445 # (u'', u'-en'),
446 # (u'', u'-er'),
447 # (u'', u'-is-mus'),
448 # (u'', u'-ität'),
449 (u'', u'-lein'),
450 (u'', u'-ne'),
451 (u'', u'-nem'),
452 (u'', u'-nen'),
453 (u'', u'-ner'),
454 (u'', u'-sche'),
455 (u'', u'-tum'),
456 (u'', u'>ar-tig'),
457 (u'', u'>chen'),
458 (u'', u'>heit'),
459 (u'', u'>keit'),
460 (u'', u'>los'),
461 (u'', u'>schaft'),
462 (u'', u'>schaft'),
463 (u'', u'>wei-se'),
464 # (u'', u'd'),
465 # (u'', u'e'),
466 # (u'', u'e-rin'),
467 # (u'', u'er'),
468 # (u'', u'is-mus'),
469 # (u'', u'm'),
470 # (u'', u'n'),
471 # (u'', u'ner'),
472 # (u'', u'r'),
473 # (u'', u's'),
474 # (u'', u's-te'),
475 # (u'', u's-te'),
476 # (u'', u's>los'),
477 # (u'', u'st'),
478 # (u'', u't'),
479 # (u'', u't-te'),
480 (u'-al', u'a-le'),
481 (u'-an', u'a-ne'),
482 (u'-at', u'a-te'),
483 (u'-ben', u'b-ne'),
484 # (u'-che', u'ch'),
485 (u'-de', u'd'),
486 (u'-en', u'>bar>keit'),
487 # (u'-en', u'e'),
488 (u'-en', u'e-ne'),
489 (u'-er', u'e-rei'),
490 (u'-er', u'e-rin'),
491 (u'-ern', u'e-re'),
492 (u'-ge', u'g'),
493 (u'-gen', u'g'),
494 (u'-in', u'i-ne'),
495 (u'-on', u'o-nen'),
496 (u'-re', u'r'),
497 (u'-re', u'rt'),
498 (u'-ren', u'r-ne'),
499 (u'-ren', u'rt'),
500 (u'-sche', u'sch'),
501 (u'-sen', u's-ne'),
502 (u'-sten', u's-mus'),
503 (u'-te',u't'),
504 (u'-tern', u't-re'),
505 (u'-ös', u'ö-se'),
506 (u'a', u'ar'),
507 (u'a', u'as'),
508 (u'b', u'-be'),
509 (u'b', u'-ber'),
510 (u'bar', u't'),
511 (u'bt', u'b-te'),
512 (u'ce', u'-cen'),
513 (u'ch', u'-che'),
514 (u'ch', u'-cher'),
515 (u'ck', u'-cke'),
516 (u'ck', u'-cker'),
517 (u'd', u'-de'),
518 (u'd', u'-dem'),
519 (u'd', u'-den'),
520 (u'd', u'-der'),
521 (u'd', u'-des'),
522 (u'd', u'>heit'),
523 (u'e', u'en'),
524 (u'e-ren', u'-ti-on'),
525 (u'e-ren', u'sch'),
526 (u'el', u'le'),
527 # (u'en', u'e'),
528 (u'en', u'em'),
529 (u'en', u'en-de'),
530 (u'en', u'end'),
531 (u'en', u'er'),
532 (u'en', u'es'),
533 (u'en', u'est'),
534 (u'en', u't'),
535 (u'en', u'te'),
536 (u'en', u'us'),
537 (u'end',u'en' ),
538 # (u'er', u'e'),
539 (u'er', u'e-rei'),
540 (u'er', u'ens'),
541 (u'er', u'in'),
542 (u'er', u'ung'),
543 (u'es', u'est'),
544 (u'es', u's-te'),
545 (u'f', u'-fe'),
546 (u'f', u'-fer'),
547 (u'g', u'-ge'),
548 (u'g', u'-gen'),
549 (u'g', u'-ger'),
550 (u'g', u'-ger'),
551 (u'g', u'-ges'),
552 (u'g', u'-gung'),
553 (u'ie', u'e'),
554 (u'in', u'en'),
555 (u'isch', u'i-sche'),
556 (u'ck', u'-cke'),
557 (u'k', u'-ke'),
558 (u'k', u'-ken'),
559 (u'k', u'-ker'),
560 (u'l', u'-le'),
561 (u'l', u'-len'),
562 (u'l', u'-ler'),
563 (u'l', u'-lis-mus'),
564 (u'le', u'-ler'),
565 (u'li-che', u'tem'),
566 (u'li-che', u'ten'),
567 (u'ln', u'-le'),
568 (u'lt', u'-le'),
569 (u'm', u'-me'),
570 (u'm', u'-mer'),
571 (u'me', u'men'),
572 (u'mus', u'men'),
573 (u'mus', u'ten'),
574 (u'mus', u'tik'),
575 (u'n', u'-at'),
576 (u'n', u'-er'),
577 (u'n', u'-ne'),
578 (u'n', u'-nen'),
579 (u'on', u'o-nis-mus'),
580 (u'n', u'-nis-mus'),
581 (u'n', u'r'),
582 (u'n', u'st'),
583 (u'n', u't'),
584 (u'n',u'-ner'),
585 (u'nd',u'n'),
586 (u'ne',u'ner'),
587 # (u'ne',u'n'),
588 (u'o',u'-on'),
589 (u'o',u'-os'),
590 (u'o',u'en'),
591 (u'on',u'o-nen'),
592 (u'p', u'-pe'),
593 (u'p', u'-pen'),
594 (u'p', u'-per'),
595 (u'ph', u'-phen'),
596 (u'ph', u'-phis-mus'),
597 (u'r', u'-re'),
598 (u'r', u'-rei'),
599 (u'r', u'-ren'),
600 (u'r', u'-rin'),
601 (u'r', u'-ris-mus'),
602 (u'r', u'-rung'),
603 (u're', u'ste'),
604 (u'ren', u'r-te'),
605 (u'ren', u'rst'),
606 (u'ren', u'rt'),
607 (u'rn', u'-re'),
608 (u'rn', u'-rung'),
609 (u'rn', u'-rung'),
610 (u'rt', u'-re'),
611 (u'rt', u'r-te'),
612 (u's', u''),
613 (u's', u'-se'),
614 (u's', u'-se-re'),
615 (u's', u'-se-res'),
616 (u's', u'-ser'),
617 (u's', u's-se'),
618 (u's', u's-ses'),
619 (u'sch', u'-sche'),
620 (u'sch', u'-schen'),
621 (u'sch', u'-scher'),
622 (u'st', u'-ste'),
623 (u'st', u'-sten'),
624 (u'st', u'n'),
625 (u't', u'-ba-re'),
626 (u't', u'>bar'),
627 (u't', u'-te'),
628 (u't', u'-te'),
629 (u't', u'-ten'),
630 (u't', u'-ter'),
631 (u't', u'-tes'),
632 (u't', u'-tin'),
633 (u't', u'-tis-mus'),
634 # (u't', u'e'),
635 (u't', u'n'),
636 (u't', u'st'),
637 (u'te', u'le'),
638 # (u'te', u't'),
639 (u'ten', u'mus'),
640 (u'ten', u'ren'),
641 (u'ten', u'tung'),
642 (u'ter', u'te-ren'),
643 (u'ti-on', u'tor'),
644 (u'um', u'a'),
645 (u'us', u'en'),
646 (u'v', u'-ve'),
647 (u'v', u'-ver'),
648 (u'v', u'-vis-mus'),
649 (u'-ve', u'v'),
650 (u'z', u'-ten'),
651 (u'z', u'-ze'),
652 (u'z', u'-zen'),
653 (u'z', u'-zer'),
654 (u'ß', u'-ße'),
655 (u'ß', u's-se'),
656 (u'ös', u'ö-se'),
660 # Zerlege einen String mit von vorn bis hinten wandernder Bruchstelle::
662 # >>> from abgleich_neueintraege import zerlege
663 # >>> list(zerlege(u'wolle'))
664 # [(u'w', u'olle'), (u'wo', u'lle'), (u'wol', u'le'), (u'woll', u'e')]
666 # ::
668 def zerlege(s):
669 for i in range(1, len(s)):
670 yield s[:i], s[i:]
672 # Zerlege Kompositum in gleichberechtigte Teile::
674 # >>> from abgleich_neueintraege import split_composits
675 # >>> from werkzeug import WordEntry
676 # >>> split_composits(WordEntry(u'Blockheizkraftwerk;Block===heiz==kraft=werk'))
677 # [u'Block', u'heiz', u'kraft', u'werk']
679 # ::
681 def split_composits(entry):
682 return [w for w in entry[1].split(u'=') if w]
684 # Zerlege String, wenn die Teile in der Wortliste vorhanden sind, setze
685 # sie neu zusammen und übernehme die Trennmarkierer:
688 def trenne_key(key, grossklein = False):
689 entries = []
690 sep = u'='
691 for k1, k2 in zerlege(key):
692 if grossklein:
693 k1 = toggle_case(k1)
694 if k1.istitle():
695 k2 = k2.title()
696 e1 = words.get(k1)
697 e2 = words.get(k2)
698 if not e2:
699 e2 = words.get(toggle_case(k2))
700 if e1 and e2:
701 if len(e1) != len(e2):
702 if len(e1) == 2:
703 e1 = [e1[1]] * len(e2)
704 elif len(e2) == 2:
705 e2 = [e2[1]] * len(e1)
706 else:
707 continue
708 entry = WordEntry(key)
709 for w1, w2 in zip(e1,e2)[1:]:
710 if w1.startswith(u'-'): # empty column -2-, -3-, ...
711 wort = w1
712 elif w2.startswith(u'-'):
713 wort = w2
714 else:
715 if grossklein:
716 w1 = toggle_case(w1)
717 w2 = w2.lower()
718 level = 1
719 while (level*sep in w1) or (level*sep in w2):
720 level += 1
721 wort = (level*sep).join([w1, w2])
722 entry.append(wort)
723 entry.conflate_fields()
724 entries.append(entry)
725 # Teste auf 3-teilige Composita und entferne die Wichtung:
726 # ['Kau==zahn=weh', 'Kau=zahn=weh'] -> ['Kau=zahn=weh']
727 if len(entries) == 2:
728 teile = [split_composits(entry) for entry in entries]
729 if teile[0] == teile[1]:
730 level = 1
731 while level*sep in teile[0]:
732 level += 1
733 entries = [entries[0]]
734 entries[0][1] = entries[0][1].replace((level+1)*sep, level*sep)
735 return entries
738 def filter_neuliste(neuwortdatei, words):
739 neue = []
740 for line in open(neuwortdatei):
741 line = line.decode('utf8').strip()
742 if line.startswith('#'):
743 neue.append(line)
744 continue
745 neukey = line.split(u';')[0]
746 if neukey in words:
747 print 'vorhanden:', line
748 elif neukey.title() in words:
749 print 'Vorhanden:', line
750 elif neukey.lower() in words:
751 print 'vorhanden (kleingeschrieben):', line
752 else:
753 neue.append(line)
754 return neue
756 def print_proposal(entry):
757 proposal = getattr(entry, "proposal", u'')
758 if proposal:
759 print u' ' + unicode(entry)
760 print u'#' + unicode(proposal)
761 else:
762 print unicode(entry)
764 if __name__ == '__main__':
766 # sys.stdout mit UTF8 encoding.
767 sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
769 # Filtern::
771 if filtern:
772 words = wordfile.asdict()
773 for line in filter_neuliste(neuwortdatei, words):
774 print line
775 sys.exit()
777 # `Wortliste` einlesen::
779 words = expand_wordfile(wordfile)
781 for alt, neu in endungen:
782 words.pop(join_word(neu), None)
784 for unwort in [u'Em']:
785 words.pop(unwort, None)
787 # # schon expandierte Liste:
788 # wordfile = WordFile('wortliste-expandiert') # + Teilwort-Entries
789 # words = wordfile.asdict()
791 neue = []
792 neue_grossklein = []
793 rest = []
795 # Erstellen der neuen Einträge::
797 proposals = [WordEntry(line.decode('utf8').strip())
798 for line in open(neuwortdatei)
799 if not line.startswith('#')]
801 for newentry in proposals:
802 OK = False
803 key = newentry[0]
805 # print key, unicode(newentry)
806 # continue
808 # Test auf vorhandene (Teil-) Wörter:
810 entry = words.get(key)
811 if entry:
812 neue.append(entry)
813 continue
814 # kleingeschrieben
815 entry = words.get(key.lower())
816 if entry:
817 neue_grossklein.append(entry)
818 continue
819 # Großgeschrieben
820 entry = words.get(key.title())
821 if entry:
822 neue_grossklein.append(entry)
823 continue
825 # Endungsabgleich::
827 for alt, neu in endungen:
828 entry = endungsabgleich(key, alt, neu, grossklein=False)
829 if entry:
830 entry.comment = newentry.comment
831 neue.append(entry)
832 OK = True
833 # break
834 if OK:
835 continue
837 for alt, neu in endungen:
838 entry = endungsabgleich(key, alt, neu, grossklein=True)
839 if entry:
840 entry.comment = newentry.comment
841 neue_grossklein.append(entry)
842 OK = True
843 # break
844 if OK:
845 continue
847 # Präfixabgleich::
849 for praefix in praefixe:
850 entry = praefixabgleich(key, praefix, grossklein=False)
851 if entry:
852 entry.comment = newentry.comment
853 neue.append(entry)
854 OK = True
855 break
856 entry = praefixabgleich(key, praefix, grossklein=True)
857 if entry:
858 entry.comment = newentry.comment
859 neue_grossklein.append(entry)
860 OK = True
861 break
862 if OK:
863 continue
865 # Zerlegen und test auf Fugen::
867 entries = trenne_key(key, grossklein=False)
868 if entries:
869 neue.extend(entries)
870 continue
871 entries = trenne_key(key, grossklein=True)
872 if entries:
873 neue_grossklein.extend(entries)
874 continue
876 # Nicht gefundene Wörter::
878 rest.append(newentry)
880 # Mehrdeutige aussortieren::
882 alle_neuen = {}
883 doppelkeys = set()
884 doppelkeys_gleich = defaultdict(int)
886 # doppelte keys finden:
887 for entry in neue + neue_grossklein:
888 key = entry[0].lower()
889 if key in alle_neuen:
890 if entry == alle_neuen[key]:
891 doppelkeys_gleich[key] += 1
892 else:
893 doppelkeys.add(key)
894 alle_neuen[key] = entry
896 # doppelte Einträge "verlegen":
897 eindeutige = []
898 eindeutige_grossklein = []
899 doppelte = []
901 for entry in neue:
902 key = entry[0].lower()
903 if key in doppelkeys:
904 doppelte.append(entry)
905 elif doppelkeys_gleich[key] > 0:
906 doppelkeys_gleich[key] -= 1
907 else:
908 eindeutige.append(entry)
910 for entry in neue_grossklein:
911 key = entry[0].lower()
912 if key in doppelkeys:
913 doppelte.append(entry)
914 elif doppelkeys_gleich[key] > 0:
915 doppelkeys_gleich[key] -= 1
916 else:
917 eindeutige_grossklein.append(entry)
920 # Vergleich mit Original::
922 identische = {}
923 for proposal in proposals:
924 key = proposal[0].lower()
925 newentry = alle_neuen.get(key)
926 if proposal == newentry:
927 identische[key] = proposal
928 else:
929 if newentry:
930 newentry.proposal = proposal
932 # Ausgabe::
934 print u'\n# identisch rekonstruiert:'
935 for entry in sorted(identische.values(), key=sortkey_duden):
936 print unicode(entry)
938 print u'\n# eindeutig abgeleitet'
939 for entry in eindeutige:
940 if entry[0].lower() not in identische:
941 print_proposal(entry)
942 print u'\n# eindeutig abgeleitet (andere Großschreibung)'
943 for entry in eindeutige_grossklein:
944 if entry[0].lower() not in identische:
945 print_proposal(entry)
947 print u'\n# mehrdeutig abgeleitet'
948 for entry in doppelte:
949 print_proposal(entry)
952 print u'\n# Rest'
954 for entry in rest:
955 print_proposal(entry)