3 # :Copyright: © 2014 Günter Milde.
4 # Released without warranty under the terms of the
5 # GNU General Public License (v. 2 or later)
8 # Erweitern der Wortliste um Kombinationen von Teilwörtern
9 # ========================================================
11 # Zerlegen von Composita an den Wortfugen und Übernahme der Teile als
12 # eigenständige Einträge.
14 # >>> from expand_teilwoerter import *
18 import os
, re
, sys
, codecs
, copy
19 from werkzeug
import (WordFile
, WordEntry
, join_word
,
20 sprachabgleich
, toggle_case
)
21 # sort.py im Überverzeichnis:
22 sys
.path
.append(os
.path
.join(os
.path
.dirname(__file__
), '..'))
23 from sort
import sortkey_duden
29 # Iterator, gibt alle geordneten Teilkombinationen zurück
31 # >>> list(multisplitter(u'test', u'='))
34 # >>> list(multisplitter(u'a=b', u'='))
35 # [u'a', u'a=b', u'b']
37 # >>> list(multisplitter(u'a=b=c', u'='))
38 # [u'a', u'a=b', u'a=b=c', u'b', u'b=c', u'c']
40 # >>> list(multisplitter('a=b=c=d', '='))
41 # ['a', 'a=b', 'a=b=c', 'a=b=c=d', 'b', 'b=c', 'b=c=d', 'c', 'c=d', 'd']
43 # >>> list(multisplitter(u'a=b==c', u'=='))
44 # [u'a=b', u'a=b==c', u'c']
46 # >>> list(multisplitter('a=b==c=de', '=='))
47 # ['a=b', 'a=b==c=de', 'c=de']
49 # >>> list(multisplitter('a=b==c=de', '==='))
52 # >>> list(multisplitter('er[<st/st=]ritt', u'='))
53 # [u'er[<st/st=]ritt']
54 # >>> list(multisplitter('Schiff[=s/s=]tau', u'='))
55 # [u'Schiff[=s/s=]tau']
56 # >>> list(multisplitter('a{ll/ll=l}ie-bend', u'='))
57 # [u'a{ll/ll=l}ie-bend']
58 # >>> list(multisplitter('Be[t=t/{tt/tt=t}]uch', u'='))
59 # [u'Be[t=t/{tt/tt=t}]uch']
63 def multisplitter(wort
, sep
):
64 specials
= re
.findall(ur
'\[.*%s.*\]|\{[^}]*%s[^}]*\}'%(sep
,sep
), wort
)
66 wort
= wort
.replace(sp
, sp
.replace(sep
, '*'))
67 parts
= wort
.split(sep
)
69 for start
in range(length
):
70 for end
in range(start
+1, length
+1):
71 part
= sep
.join(parts
[start
:end
])
73 part
= part
.replace('*', sep
)
77 # Gib eine Liste möglicher Zerlegungen eines Kompositums zurück.
78 # Berücksichtige dabei die Bindungsstärke bis zum Level 3
79 # ("===", zur Zeit höchste Auszeichnung in der Wortliste).
81 # >>> multisplit(u'test')
84 # >>> multisplit(u'a=b')
85 # [u'a', u'a=b', u'b']
87 # >>> multisplit(u'a=b=c')
88 # [u'a', u'a=b', u'a=b=c', u'b', u'b=c', u'c']
90 # >>> multisplit(u'a==b=c')
91 # [u'a', u'a==b=c', u'b', u'b=c', u'c']
93 # >>> multisplit(u'a==b=c==d')
94 # [u'a', u'a==b=c', u'a==b=c==d', u'b', u'b=c', u'c', u'b=c==d', u'd']
96 # >>> for w in multisplit(u'Brenn=stoff==zel-len===an<trieb'):
101 # Brenn=stoff==zel-len
103 # Brenn=stoff==zel-len===an<trieb
108 def multisplit(wort
):
110 for p3
in multisplitter(wort
, u
'==='):
114 for p2
in multisplitter(p3
, u
'=='):
118 for p1
in multisplitter(p2
, u
'='):
120 if wort
[:2].istitle():
121 parts
= [part
[0].title() + part
[1:] for part
in parts
]
124 # Gib eine Liste von allen (sinnvollen) Zerlegungen eines WordEntry zurück
126 # >>> from werkzeug import WordEntry
128 # >>> split_entry(WordEntry(u'Aachen;Aa-chen'))
129 # [[u'Aachen', u'Aa-chen']]
130 # >>> aalbestand = WordEntry(u'Aalbestand;Aal=be<stand')
131 # >>> split_entry(aalbestand)
132 # [[u'Aal', u'Aal'], [u'Aalbestand', u'Aal=be<stand'], [u'Bestand', u'Be<stand']]
134 # >>> godi = WordEntry(u'Abendgottesdienste;-2-;Abend==got-tes=dien-ste;Abend==got-tes=diens-te')
135 # >>> for entry in split_entry(godi):
137 # Abend;-2-;Abend;Abend
138 # Abendgottesdienste;-2-;Abend==got-tes=dien-ste;Abend==got-tes=diens-te
139 # Gottes;-2-;Got-tes;Got-tes
140 # Gottesdienste;-2-;Got-tes=dien-ste;Got-tes=diens-te
141 # Dienste;-2-;Dien-ste;Diens-te
143 # >>> bb = WordEntry(u'Biberbettuch;-2-;Bi-ber==be[t=t/{tt/tt=t}]uch')
144 # >>> for entry in split_entry(bb):
147 # Biberbettuch;-2-;Bi-ber==be[t=t/{tt/tt=t}]uch
148 # Bettuch;-2-;Be[t=t/{tt/tt=t}]uch
152 def split_entry(entry
):
156 for col
in range(1, len(entry
)):
159 continue # nichts zu splitten
160 parts
= multisplit(wort
)
162 # Kopien des Originaleintrags erstellen
165 entries
.append(copy
.copy(entry
))
166 entries
[-1][0] = join_word(part
)
168 for i
in range(len(parts
)):
169 entries
[i
][col
] = parts
[i
]
173 e
.conflate_fields() # Sprachabgleich
178 # Gib ein Dictionary mit Einträgen der Wortliste und Teilwortkombinationen zurück:
180 def expand_wordfile(wordfile
):
181 words
= {} # Wörter aus der Liste
183 for entry
in wordfile
:
185 entries
= split_entry(entry
)
186 except IndexError: # unterschiedliche Zerlegung je nach Sprache
187 # print "problematisch", unicode(entry)
188 words
[entry
[0].lower()] = entry
192 if len(entries
) == 1 or e
[0].lower() not in words
:
193 words
[e
[0].lower()] = e
197 if __name__
== '__main__':
199 # sys.stdout mit UTF8 encoding.
200 sys
.stdout
= codecs
.getwriter('UTF-8')(sys
.stdout
)
202 # `Wortliste` einlesen::
204 wordfile
= WordFile('../../wortliste') # ≅ 400 000 Einträge/Zeilen
206 words
= expand_wordfile(wordfile
)
208 print len(words
), "expandiert"
210 outfile
= open('wortliste-expandiert', 'w')
212 for entry
in sorted(words
.values(), key
=sortkey_duden
):
213 outfile
.write(str(entry
))