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
, sortkey_duden
)
26 # Iterator, gibt alle geordneten Teilkombinationen zurück
28 # >>> list(multisplitter(u'test', u'='))
31 # >>> list(multisplitter(u'a=b', u'='))
32 # [u'a', u'a=b', u'b']
34 # >>> list(multisplitter(u'a=b=c', u'='))
35 # [u'a', u'a=b', u'a=b=c', u'b', u'b=c', u'c']
37 # >>> list(multisplitter('a=b=c=d', '='))
38 # ['a', 'a=b', 'a=b=c', 'a=b=c=d', 'b', 'b=c', 'b=c=d', 'c', 'c=d', 'd']
40 # >>> list(multisplitter(u'a=b==c', u'=='))
41 # [u'a=b', u'a=b==c', u'c']
43 # >>> list(multisplitter('a=b==c=de', '=='))
44 # ['a=b', 'a=b==c=de', 'c=de']
46 # >>> list(multisplitter('a=b==c=de', '==='))
49 # >>> list(multisplitter('er[<st/st=]ritt', u'='))
50 # [u'er[<st/st=]ritt']
51 # >>> list(multisplitter('Schiff[=s/s=]tau', u'='))
52 # [u'Schiff[=s/s=]tau']
53 # >>> list(multisplitter('a{ll/ll=l}ie-bend', u'='))
54 # [u'a{ll/ll=l}ie-bend']
55 # >>> list(multisplitter('Be[t=t/{tt/tt=t}]uch', u'='))
56 # [u'Be[t=t/{tt/tt=t}]uch']
60 def multisplitter(wort
, sep
):
61 specials
= re
.findall(ur
'\[.*%s.*\]|\{[^}]*%s[^}]*\}'%(sep
,sep
), wort
)
63 wort
= wort
.replace(sp
, sp
.replace(sep
, '*'))
64 parts
= wort
.split(sep
)
66 for start
in range(length
):
67 for end
in range(start
+1, length
+1):
68 part
= sep
.join(parts
[start
:end
])
70 part
= part
.replace('*', sep
)
74 # Gib eine Liste möglicher Zerlegungen eines Kompositums zurück.
75 # Berücksichtige dabei die Bindungsstärke bis zum Level 3
76 # ("===", zur Zeit höchste Auszeichnung in der Wortliste).
78 # >>> multisplit(u'test')
81 # >>> multisplit(u'a=b')
82 # [u'a', u'a=b', u'b']
84 # >>> multisplit(u'a=b=c')
85 # [u'a', u'a=b', u'a=b=c', u'b', u'b=c', u'c']
87 # >>> multisplit(u'a==b=c')
88 # [u'a', u'a==b=c', u'b', u'b=c', u'c']
90 # >>> multisplit(u'a==b=c==d')
91 # [u'a', u'a==b=c', u'a==b=c==d', u'b', u'b=c', u'c', u'b=c==d', u'd']
93 # >>> for w in multisplit(u'Brenn=stoff==zel-len===an<trieb'):
98 # Brenn=stoff==zel-len
100 # Brenn=stoff==zel-len===an<trieb
105 def multisplit(wort
):
107 for p3
in multisplitter(wort
, u
'==='):
111 for p2
in multisplitter(p3
, u
'=='):
115 p2
= p2
.replace(u
'<=', u
'<')
116 p2
= p2
.replace(u
'=>', u
'>')
117 for p1
in multisplitter(p2
, u
'='):
119 if wort
[:2].istitle():
120 parts
= [part
[0].title() + part
[1:] for part
in parts
]
123 # Gib eine Liste von allen (sinnvollen) Zerlegungen eines WordEntry zurück
125 # >>> from werkzeug import WordEntry
127 # >>> split_entry(WordEntry(u'Aachen;Aa-chen'))
128 # [[u'Aachen', u'Aa-chen']]
129 # >>> aalbestand = WordEntry(u'Aalbestand;Aal=be<stand')
130 # >>> split_entry(aalbestand)
131 # [[u'Aal', u'Aal'], [u'Aalbestand', u'Aal=be<stand'], [u'Bestand', u'Be<stand']]
133 # >>> godi = WordEntry(u'Abendgottesdienste;-2-;Abend==got-tes=dien-ste;Abend==got-tes=diens-te')
134 # >>> for entry in split_entry(godi):
136 # Abend;-2-;Abend;Abend
137 # Abendgottesdienste;-2-;Abend==got-tes=dien-ste;Abend==got-tes=diens-te
138 # Gottes;-2-;Got-tes;Got-tes
139 # Gottesdienste;-2-;Got-tes=dien-ste;Got-tes=diens-te
140 # Dienste;-2-;Dien-ste;Diens-te
142 # >>> bb = WordEntry(u'Biberbettuch;-2-;Bi-ber==be[t=t/{tt/tt=t}]uch')
143 # >>> for entry in split_entry(bb):
146 # Biberbettuch;-2-;Bi-ber==be[t=t/{tt/tt=t}]uch
147 # Bettuch;-2-;Be[t=t/{tt/tt=t}]uch
151 def split_entry(entry
):
155 for col
in range(1, len(entry
)):
158 continue # nichts zu splitten
159 parts
= multisplit(wort
)
161 # Kopien des Originaleintrags erstellen
164 entries
.append(copy
.copy(entry
))
165 entries
[-1][0] = join_word(part
)
167 for i
in range(len(parts
)):
168 entries
[i
][col
] = parts
[i
]
172 e
.conflate_fields() # Sprachabgleich
177 # Gib ein Dictionary mit Einträgen der Wortliste und Teilwortkombinationen zurück:
179 def expand_wordfile(wordfile
):
180 words
= {} # Wörter aus der Liste
182 for entry
in wordfile
:
184 entries
= split_entry(entry
)
185 except IndexError: # unterschiedliche Zerlegung je nach Sprache
186 # print "problematisch", unicode(entry)
187 words
[entry
[0]] = entry
191 if (len(entries
) == 1
192 or (e
[0].lower() not in words
and e
[0].title() not in words
)
193 or len(e
[0]) <= 3 and len(e
) == 2 # kurze einfache Wörter
200 key
= join_word(wort
)
201 return (key
.title() in words
) or (key
.lower() in words
) or (len(wort
)<4)
203 if __name__
== '__main__':
205 # sys.stdout mit UTF8 encoding.
206 sys
.stdout
= codecs
.getwriter('UTF-8')(sys
.stdout
)
208 # `Wortliste` einlesen::
210 wordfile
= WordFile('../../wortliste') # ≅ 400 000 Einträge/Zeilen
214 # sprachvariante = 'de-1996'
215 # sprachvariante = 'de-1901'
216 # words = wordfile.asdict()
217 # for entry in words.itervalues():
218 # wort = entry.get(sprachvariante)
221 # if (u'<=' in wort or u'=>' in wort or u'==' in wort):
223 # parts = [part for part in multisplit(wort)
224 # if u'=' not in part]
225 # if len(parts) == 3:
226 # if parts[1] == u'zu':
228 # if (exists(parts[0]) and exists(''.join(parts[1:]))
229 # and not(exists(parts[-1])
230 # and (exists(''.join(parts[:-1])) or exists(''.join(parts[:-1])+u's')))
232 # for i in range(1,len(parts)):
233 # parts[i] = parts[i].lower()
234 # wort = u'=='.join([parts[0], u'='.join(parts[1:])])
235 # entry.set(wort, sprachvariante)
236 # sprachabgleich(entry)
237 # print unicode(entry)
241 # expandieren und Speichern::
243 words
= expand_wordfile(wordfile
)
245 print len(words
), "expandiert"
247 outfile
= open('wortliste-expandiert', 'w')
249 for entry
in sorted(words
.values(), key
=sortkey_duden
):
250 outfile
.write(str(entry
))