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 ):
5155 p = 0
5256 pat = re .compile ("|" .join (pat_tcc ))
53- while p < len (w ):
57+ while p < len (w ):
5458 m = pat .match (w [p :])
5559 if m :
5660 n = m .span ()[1 ]
5761 else :
5862 n = 1
59- yield w [p :p + n ]
63+ yield w [p :p + n ]
6064 p += n
6165
66+
6267def tcc_pos (text ):
6368 p_set = set ()
6469 p = 0
6570 for w in tcc (text ):
6671 p += len (w )
6772 p_set .add (p )
6873 return p_set
69- def serialize (words_at , p , p2 ):
70- # find path ทั้งหมด แบบ depth first
71- for w in words_at [p ]:
72- p_ = p + len (w )
73- if p_ == p2 :
74- yield [w ]
75- elif p_ < p2 :
76- for path in serialize (words_at , p_ , p2 ):
77- yield [w ]+ path
78- def onecut (text ,data = ['' ]):
79- if (data != ['' ]):
80- trie = Trie (data )
81- else :
82- trie = Trie (get_data ())
83- words_at = defaultdict (list ) # main data structure
84- allow_pos = tcc_pos (text ) # ตำแหน่งที่ตัด ต้องตรงกับ tcc
85-
86- q = [0 ] # min-heap queue
87- last_p = 0 # last position for yield
88- 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_ )
9774
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 ):
75+
76+ def serialize (words_at , p , p2 ):
77+ # find path ทั้งหมด แบบ depth first
78+ for w in words_at [p ]:
79+ p_ = p + len (w )
80+ if p_ == p2 :
81+ yield [w ]
82+ elif p_ < p2 :
83+ for path in serialize (words_at , p_ , p2 ):
84+ yield [w ] + path
85+
86+
87+ def onecut (text , data = ['' ]):
88+ if (data != ['' ]):
89+ trie = Trie (data )
90+ else :
91+ trie = THAI_WORDS
92+ words_at = defaultdict (list ) # main data structure
93+ allow_pos = tcc_pos (text ) # ตำแหน่งที่ตัด ต้องตรงกับ tcc
94+
95+ q = [0 ] # min-heap queue
96+ last_p = 0 # last position for yield
97+ while q [0 ] < len (text ):
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 )
102130 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-
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