66# Határozzuk meg a normaliser.py könyvtárát
77base_dir = os .path .dirname (os .path .abspath (__file__ ))
88
9+ # Római számokat arab számmá alakító segédfüggvény
10+ def roman_to_int (s ):
11+ roman_map = {'I' : 1 , 'V' : 5 , 'X' : 10 , 'L' : 50 , 'C' : 100 , 'D' : 500 , 'M' : 1000 }
12+ total = 0
13+ prev = 0
14+ for char in reversed (s ):
15+ val = roman_map [char ]
16+ if val < prev :
17+ total -= val
18+ else :
19+ total += val
20+ prev = val
21+ return total
22+
23+ def replace_roman_numerals (text ):
24+ """
25+ Minden olyan tokent, ami csak római számból áll (I,V,X,L,C,D,M),
26+ opcionálisan egy végponttal, arab számmá alakítjuk.
27+ Pl. 'VI' -> '6', 'IX.' -> '9.'
28+ """
29+ pattern = re .compile (r'\b([MDCLXVI]+)(\.)?\b' )
30+ def repl (m ):
31+ roman , dot = m .group (1 ), m .group (2 ) or ''
32+ # csak akkor alakítjuk, ha érvényes római számként értelmezhető
33+ try :
34+ arab = roman_to_int (roman )
35+ except KeyError :
36+ return m .group (0 )
37+ return f"{ arab } { dot } "
38+ return pattern .sub (repl , text )
39+
940def load_force_changes (filename = "force_changes.csv" ):
10- # A fájl elérési útja a base_dir könyvtárhoz képest
41+ """
42+ A force_changes.csv most négy oszlopos:
43+ key, value, spaces_before, spaces_after
44+ """
1145 file_path = os .path .join (base_dir , filename )
1246 force_changes = {}
1347 with open (file_path , encoding = 'utf-8' ) as csvfile :
1448 reader = csv .reader (csvfile )
1549 for row in reader :
16- if row :
17- key , value = row
18- force_changes [key .strip ()] = value .strip ()
50+ if not row :
51+ continue
52+ key , value , spaces_before , spaces_after = row
53+ key = key .strip ()
54+ value = value .strip ()
55+ # számokra castelünk
56+ before = int (spaces_before .strip ())
57+ after = int (spaces_after .strip ())
58+ force_changes [key ] = (value , before , after )
1959 return force_changes
2060
2161def apply_force_changes (text , force_changes ):
22- # Fix cserék alkalmazása a szövegre
23- for key , value in force_changes .items ():
24- text = text .replace (key , f' { value } ' )
62+ """
63+ A CSV-ben megadott szócsere után annyi szóközt teszünk
64+ előre-utólag, amennyit a 3–4. oszlopban látunk.
65+ """
66+ for key , (value , before , after ) in force_changes .items ():
67+ replacement = ' ' * before + value + ' ' * after
68+ text = text .replace (key , replacement )
2569 return text
2670
2771def load_changes (filename = "changes.csv" ):
@@ -43,33 +87,19 @@ def apply_changes(text, changes):
4387 text = re .sub (pattern , value , text , flags = re .IGNORECASE )
4488 return text
4589
46- ordinals = {
47- 1 : 'első' ,
48- 2 : 'második' ,
49- 3 : 'harmadik' ,
50- 4 : 'negyedik' ,
51- 5 : 'ötödik' ,
52- 6 : 'hatodik' ,
53- 7 : 'hetedik' ,
54- 8 : 'nyolcadik' ,
55- 9 : 'kilencedik' ,
56- 10 : 'tizedik' ,
57- # További sorszámok hozzáadása szükség szerint
58- }
5990
60- def replace_ordinals (text , ordinals ):
61- # Sorszámok átírása, kivéve ha a mondat végén vannak
62- def repl (match ):
63- num = int (match .group (1 ))
64- start , end = match .span ()
65- following_text = text [end :]
66- if re .match (r'^\s*$' , following_text ) or re .match (r'^\s*[\.!\?]' , following_text ):
67- return match .group (0 )
68- ordinal_word = ordinals .get (num , num2words (num , to = 'ordinal' , lang = 'hu' ))
69- return ordinal_word
70- pattern = r'(\d+)\.(?![\s]*$|[\s]*[\.!\?])'
71- text = re .sub (pattern , repl , text )
72- return text
91+ def replace_ordinals (text ):
92+ """
93+ Bármilyen nagyságú arab számból álló sorszámot (pl. 1233.)
94+ átír num2words segítségével magyar ordítóvá.
95+ A patrón biztosítja, hogy a mondatvégén álló számot ponttal ne bántsa.
96+ """
97+ pattern = re .compile (r'\b(\d+)\.(?!\s*$|\s*[\.!\?])' )
98+ def repl (m ):
99+ num = int (m .group (1 ))
100+ # a num2words kész ordító formát ad vissza, pl. 'ezerkettőszázharmincháromadik'
101+ return num2words (num , to = 'ordinal' , lang = 'hu' )
102+ return pattern .sub (repl , text )
73103
74104months = {
75105 'jan.' : 'január' ,
@@ -142,52 +172,67 @@ def day_to_text(day):
142172 return day_words .get (day , num2words (day , lang = 'hu' ) + 'ika' )
143173
144174def replace_dates (text ):
145- # Dátumok felismerése és átírása
175+ # 0. Külön kezeli az "N-án" vagy "N-én" formátumot
176+ pattern0 = re .compile (r'\b(\d{1,2})-(án|én)\b' )
177+ def repl0 (m ):
178+ day = int (m .group (1 ))
179+ suffix = m .group (2 ) # 'án' vagy 'én'
180+ ordinal = num2words (day , to = 'ordinal' , lang = 'hu' )
181+ return ordinal + suffix
182+ text = pattern0 .sub (repl0 , text )
183+
184+ # --- először mindegyik dátumformátum, mint eddig ---
146185 month_abbrs = '|' .join (re .escape (k ) for k in months .keys ())
147186
148- # Év.Hónap.Nap formátum (2015.10.23.)
149- pattern1 = r'(\d{4})\.(\d{1,2})\.(\d{1,2})\.'
150- def repl1 (match ):
151- year = int (match .group (1 ))
152- month = int (match .group (2 ))
153- day = int (match .group (3 ))
187+ # 1. Év.Hónap.Nap formátum (2015.10.23.)
188+ pattern1 = re .compile (r'(\d{4})\.(\d{1,2})\.(\d{1,2})\.' )
189+ def repl1 (m ):
190+ year , month , day = map (int , m .groups ())
154191 year_text = num2words (year , lang = 'hu' )
155192 month_text = months_numbers .get (month , '' )
156193 day_text = day_to_text (day )
157194 return f'{ year_text } { month_text } { day_text } '
158- text = re .sub (pattern1 , repl1 , text )
195+ text = pattern1 .sub (repl1 , text )
159196
160- # Év.HónapRöv.Nap formátum (2015.okt.23.)
161- pattern2 = r'(\d{4})\.(' + month_abbrs + r')(\d{1,2})\.'
162- def repl2 (match ):
163- year = int (match .group (1 ))
164- month_abbr = match .group (2 )
165- day = int (match .group (3 ))
197+ # 2. Év.HónapRöv.Nap formátum (2015.okt.23.)
198+ pattern2 = re . compile ( r'(\d{4})\.(' + month_abbrs + r')(\d{1,2})\.' )
199+ def repl2 (m ):
200+ year = int (m .group (1 ))
201+ month_abbr = m .group (2 )
202+ day = int (m .group (3 ))
166203 year_text = num2words (year , lang = 'hu' )
167204 month_text = months .get (month_abbr .lower (), month_abbr )
168205 day_text = day_to_text (day )
169206 return f'{ year_text } { month_text } { day_text } '
170- text = re .sub (pattern2 , repl2 , text )
207+ text = pattern2 .sub (repl2 , text )
171208
172- # HónapRöv.Nap formátum (okt.23.)
173- pattern3 = r'(' + month_abbrs + r')(\d{1,2})\.'
174- def repl3 (match ):
175- month_abbr = match .group (1 )
176- day = int (match .group (2 ))
209+ # 3. HónapRöv.Nap formátum (okt.23.)
210+ pattern3 = re . compile ( r'(' + month_abbrs + r')(\d{1,2})\.' )
211+ def repl3 (m ):
212+ month_abbr = m .group (1 )
213+ day = int (m .group (2 ))
177214 month_text = months .get (month_abbr .lower (), month_abbr )
178215 day_text = day_to_text (day )
179216 return f'{ month_text } { day_text } '
180- text = re .sub (pattern3 , repl3 , text )
217+ text = pattern3 .sub (repl3 , text )
181218
182- # HónapRöv. Nap-án formátum (okt. 23-án)
183- pattern4 = r'(' + month_abbrs + r')\s+(\d{1,2})-án'
184- def repl4 (match ):
185- month_abbr = match .group (1 )
186- day = int (match .group (2 ))
219+ # 4. HónapRöv. Nap-án formátum (okt. 23-án)
220+ pattern4 = re . compile ( r'(' + month_abbrs + r')\s+(\d{1,2})-án' )
221+ def repl4 (m ):
222+ month_abbr = m .group (1 )
223+ day = int (m .group (2 ))
187224 month_text = months .get (month_abbr .lower (), month_abbr )
188225 day_text = day_to_text (day ) + 'n'
189226 return f'{ month_text } { day_text } '
190- text = re .sub (pattern4 , repl4 , text )
227+ text = pattern4 .sub (repl4 , text )
228+
229+ # 5. Maradék rövid hónapnevek: dec. -> december stb.
230+ # (ezeket nem köti nap vagy év, csak önállóan szerepelnek)
231+ pattern5 = re .compile (r'(?<!\w)(' + month_abbrs + r')(?!\w)' )
232+ def repl5 (m ):
233+ abb = m .group (1 ).lower ()
234+ return months .get (abb , abb )
235+ text = pattern5 .sub (repl5 , text )
191236
192237 return text
193238
@@ -238,11 +283,12 @@ def normalize(text):
238283 force_changes = load_force_changes ('force_changes.csv' )
239284 changes = load_changes ('changes.csv' )
240285
286+ text = replace_roman_numerals (text )
241287 text = apply_force_changes (text , force_changes )
242288 text = apply_changes (text , changes )
243289 text = replace_dates (text )
244290 text = replace_times (text )
245- text = replace_ordinals (text , ordinals )
291+ text = replace_ordinals (text )
246292 text = replace_numbers (text )
247293 text = remove_unwanted_characters (text )
248294 text = remove_duplicate_spaces (text )
@@ -252,6 +298,7 @@ def normalize(text):
252298
253299if __name__ == "__main__" :
254300 # Példa szöveg
255- sample_text = "Ez egy példa, KENY, szöveg 10% és 7:15 időponttal 2015.10.23. dátummal. Chartmen"
301+ sample_text = ("Ez egy példa szöveg 2023.10.23-án, ami tartalmaz római számokat: VI, és arab számokat: 1234. "
302+ "Ezen kívül van benne időpont is: 12:30:45, és dátumok is: okt. 23-án." )
256303 normalized_text = normalize (sample_text )
257304 print (normalized_text )
0 commit comments