11# -*- coding: utf-8 -*-
2+
23'''ตัวตัดคำภาษาไทยโดยใช้หลักการ maximal matching และ TCC
34พัฒนาโดยคุณ Korakot Chaovavanich
45Notebook : https://colab.research.google.com/notebook#fileId=1V1Z657_5eSWPo8rLfVRwA0A5E4vkg7SI
56'''
6- from __future__ import absolute_import ,unicode_literals
7+ from __future__ import absolute_import , unicode_literals
78import re
89from collections import defaultdict
910from heapq import heappush , heappop # for priority queue
1011from marisa_trie import Trie
11- from pythainlp .corpus .thaiword import get_data # ดึงข้อมูลรายการคำในภาษาไทย
12+ from pythainlp .corpus .thaiword import get_data # ดึงข้อมูลรายการคำในภาษาไทย
1213
1314
1415# ช่วยตัดพวกภาษาอังกฤษ เป็นต้น
4546แccc์
4647โctะ
4748[เ-ไ]ct
48- """ .replace ('c' ,'[ก-ฮ]' ).replace ('t' , '[่-๋]?' ).split ()
49+ """ .replace ('c' , '[ก-ฮ]' ).replace ('t' , '[่-๋]?' ).split ()
50+
51+ THAI_WORDS = Trie (get_data ())
52+
4953
5054def tcc (w ):
51- p = 0
52- pat = re .compile ("|" .join (pat_tcc ))
53- while p < len (w ):
54- m = pat .match (w [p :])
55- if m :
56- n = m .span ()[1 ]
57- else :
58- n = 1
59- yield w [p :p + n ]
60- p += n
55+ p = 0
56+ pat = re .compile ("|" .join (pat_tcc ))
57+ while p < len (w ):
58+ m = pat .match (w [p :])
59+ if m :
60+ n = m .span ()[1 ]
61+ else :
62+ n = 1
63+ yield w [p :p + n ]
64+ p += n
65+
6166
6267def tcc_pos (text ):
63- p_set = set ()
64- p = 0
65- for w in tcc (text ):
66- p += len (w )
67- p_set .add (p )
68- return p_set
69- def serialize (words_at , p , p2 ):
68+ p_set = set ()
69+ p = 0
70+ for w in tcc (text ):
71+ p += len (w )
72+ p_set .add (p )
73+ return p_set
74+
75+
76+ def serialize (words_at , p , p2 ):
7077 # find path ทั้งหมด แบบ depth first
7178 for w in words_at [p ]:
7279 p_ = p + len (w )
73- if p_ == p2 :
80+ if p_ == p2 :
7481 yield [w ]
7582 elif p_ < p2 :
7683 for path in serialize (words_at , p_ , p2 ):
77- yield [w ]+ path
78- def onecut (text ,data = ['' ]):
79- if (data != ['' ]):
80- trie = Trie (data )
84+ yield [w ] + path
85+
86+
87+ def onecut (text , data = ['' ]):
88+ if (data != ['' ]):
89+ trie = Trie (data )
8190 else :
82- trie = Trie ( get_data ())
91+ trie = THAI_WORDS
8392 words_at = defaultdict (list ) # main data structure
8493 allow_pos = tcc_pos (text ) # ตำแหน่งที่ตัด ต้องตรงกับ tcc
85-
94+
8695 q = [0 ] # min-heap queue
8796 last_p = 0 # last position for yield
8897 while q [0 ] < len (text ):
89- p = heappop (q )
90-
91- for w in trie .prefixes (text [p :]):
92- p_ = p + len (w )
93- if p_ in allow_pos : # เลือกที่สอดคล้อง tcc
94- words_at [p ].append (w )
95- if p_ not in q :
96- heappush (q , p_ )
97-
98- # กรณี length 1 คือ ไม่กำกวมแล้ว ส่งผลลัพธ์ก่อนนี้คืนได้
99- if len (q )== 1 :
100- paths = serialize (words_at , last_p , q [0 ])
101- for w in min (paths , key = len ):
102- yield w
103- last_p = q [0 ]
104-
105- # กรณี length 0 คือ ไม่มีใน dict
106- if len (q )== 0 :
107- m = pat_eng .match (text [p :])
108- if m : # อังกฤษ, เลข, ว่าง
109- i = p + m .end ()
110- else : # skip น้อยที่สุด ที่เป็นไปได้
111- for i in range (p + 1 , len (text )):
112- if i in allow_pos : # ใช้ tcc ด้วย
113- ww = trie .prefixes (text [i :])
114- m = pat_eng .match (text [i :])
115- if ww or m :
116- break
117- else :
118- i = len (text )
119- w = text [p :i ]
120- words_at [p ].append (w )
121- yield w
122- last_p = i
123- heappush (q , i )
124-
98+ p = heappop (q )
99+
100+ for w in trie .prefixes (text [p :]):
101+ p_ = p + len (w )
102+ if p_ in allow_pos : # เลือกที่สอดคล้อง tcc
103+ words_at [p ].append (w )
104+ if p_ not in q :
105+ heappush (q , p_ )
106+
107+ # กรณี length 1 คือ ไม่กำกวมแล้ว ส่งผลลัพธ์ก่อนนี้คืนได้
108+ if len (q ) == 1 :
109+ paths = serialize (words_at , last_p , q [0 ])
110+ for w in min (paths , key = len ):
111+ yield w
112+ last_p = q [0 ]
113+
114+ # กรณี length 0 คือ ไม่มีใน dict
115+ if len (q ) == 0 :
116+ m = pat_eng .match (text [p :])
117+ if m : # อังกฤษ, เลข, ว่าง
118+ i = p + m .end ()
119+ else : # skip น้อยที่สุด ที่เป็นไปได้
120+ for i in range (p + 1 , len (text )):
121+ if i in allow_pos : # ใช้ tcc ด้วย
122+ ww = trie .prefixes (text [i :])
123+ m = pat_eng .match (text [i :])
124+ if ww or m :
125+ break
126+ else :
127+ i = len (text )
128+ w = text [p :i ]
129+ words_at [p ].append (w )
130+ yield w
131+ last_p = i
132+ heappush (q , i )
133+
125134# ช่วยให้ไม่ต้องพิมพ์ยาวๆ
126- def mmcut (text ,data = ['' ]):
127- return list (onecut (text ,data = data ))
135+
136+
137+ def mmcut (text , data = ['' ]):
138+ return list (onecut (text , data = data ))
0 commit comments