Mar 5 2010

ตัดคำไทยด้วย C#

Category: OOAD | .NET | Java | Nativem3rLinEz @ 02:15

WARNING: Highly technical blog ahead

กาลครั้งหนึ่งนานมาแล้ว … อาจารย์สมชายแห่ง CP เคยเอารัฐธรรมนูญฉบับเก่ากับฉบับใหม่มาเทียบความถี่ในการปรากฎของคำ ตอนนั้นผมอึ้งมากที่รู้ว่า Java มันตัดคำไทยได้ด้วย แบบ built-in มาไม่ต้องหา library อะไรมาเพิ่มเลย >_<  ถ้าผมเข้าใจไม่ผิด Java ใช้ ICU ของ IBM ที่เป็น open source แต่ตัวที่อยู่ใน class library ของ Java จะเป็นเวอร์ชันเก่ากว่าหน่อย

เจ้า ICU ที่ว่านี่นอกจากตัดคำได้ (Boundary Analysis) แล้วมันยังทำอย่างอื่นที่เกี่ยวกับกับ localization & internationalization ได้อีกมากมายก่ายกองครับ ลองเข้าไปดูกันเอง IBM ทำไว้สองชุดคือ ICU4C และ ICU4J สำหรับ C, C++ และ Java (ไม่มี .NET แป่วว) ถ้าใครทันสมัยใช้ Firefox ที่ยังตัดคำไทยไม่ค่อยจะคล่องอาจจะได้ยินชื่อนี้บ่อย เพราะมีคนไทยฮาร์ดคอร์มากมายเอาโค้ด Firefox มาแก้ใส่ ICU ให้ตัดคำแล้ว build ใหม่ … แค่ฟังก็อยากจะอ้วกออกมาเป็น pointer กับไฟล์ .h แล้วว =__=’

ด้วยความที่ 3 วันนี้ผมเมาจัดหรือยังไงไม่ทราบ เลยใช้เวลาว่างอันมีอยู่น้อยนิดไปพยายามทำ binding ให้เรียกใช้ ICU จาก C# (และ .NET) ได้ครับ! ก่อนทำก็หา best practice โดยการไปถามที่แหล่งประจำเล็กน้อย ได้คำตอบมาแค่อันเดียวน่าเศร้าใจ TvT

ผมเข้าใจว่าการทำ binding มันจะต่างจาก wrapper ตรงที่ เราต้องนำเสนอ interface เดียว (หรือคล้ายๆ) กับที่ underlying C++ classes มันใช้อยู่ให้กับผู้ใช้ ส่วนการทำ wrapper มันเหมือนกับว่าเราไปสร้างอะไรซักอย่างหุ้ม C++ classes เหล่านั้นไว้ และให้ผู้ใช้เรียกใช้งานผ่าน interface ของเรา (โดยไม่รู้ว่าข้างในมีอะไรอยู่บ้าง – Facade Pattern อ่านว่า “ฟา-ซ้าด”) ซึ่งการทำ wrapper นี่มันง่ายกว่าโขเลยน่ะ

หลังจากลองถูๆไถๆ ใช้พลังกับ C++/CLI เหมือนที่เคยใช้ในซีเนียร์โปรเจค ก็ออกมาเป็นรูปเป็นร่าง อยู่ที่ ICU4NET สามารถลองดาวน์โหลดไปใช้ได้ ถึงชื่อจะบอกว่า ICU4NET แต่จริงๆแล้วตอนนี้มันมี class ที่ใช้งานได้อยู่ class เดียวคือ BreakIterator =_=” ตั้งใจไว้ว่าจะจัดการกับ class ในกลุ่ม boundary analysis ให้หมด

เอาโค้ดตัวอย่างให้ดูเล็กน้อย อันแรกเป็นแบบดั้งเดิม ลักษณะเดียวกับที่เขียนใน ICU4J และ ICU4C

private List<string> WordBreak(string text)
{
var sb = new StringBuilder();
var col = new List<string>();

using (BreakIterator bi = BreakIterator.CreateWordInstance(Locale.GetUS()))
{
bi.SetText(text);
int start = bi.First(), end = bi.Next();
while (end != BreakIterator.DONE)
{
col.Add(text.Substring(start, end - start));
start = end; end = bi.Next();
}
}

return col;
}

ส่วนอันนี้ผมเขียน Extension Method เพิ่มให้มัน return เป็น IEnumerable ได้ พวกขา 3.5 จะได้เล่นซนแบบนี้ได้ :’)

using (BreakIterator bi = BreakIterator.CreateWordInstance(Locale.GetUS()))
{
bi.SetText(uxText.Text);

// requires ICU4NETExtension to use Enumerate extension method
MessageBox.Show(string.Join(Environment.NewLine, bi.Enumerate()
.GroupBy(w => w)
.OrderBy(x => x.Count())
.Reverse()
.Select(x => x.Key + " : " + x.Count())
.Take(10)
.ToArray()));
}

ตอนแรกตั้งใจว่า ส่วนที่น่าจะเอาไปเล่นได้หลักๆคงเป็นพวก ASP.NET Web App แหละ แต่นั่งคิดๆดูแล้วมันมีส่วนประกอบที่เป็น library native ของ ICU หลายอันอยู่ ถ้าเข้าใจไม่ผิดคงมีปัญหากับเรื่อง trust level ของ IIS พอสมควร …

ผลพลอยได้จากการผลาญเวลา (แบบไร้เหตุผล เอามันส์ล้วนๆ) ครั้งนี้คือ ได้ศึกษา C# เพิ่มอีกนิดหน่อย แล้วก็ลองใช้ C++/CLI อีกนิสสสนึง หลังๆมานี่อยู่ที่ทำงานได้ใช้แต่ C++ จนรู้สึกตัวเองตามโลก C# ไม่ทัน มาอ่านโค้ดของ @chakrit (ขา 3.5 ตัวพ่อ) ทีนี่นั่งงงอยู่หลายนาที –..-‘ เออออ … น้ำหลักลดด้วยนะ ^ ^

จากประสบการณ์ ด้วยหัวข้อยบลอกประมาณนี้ ผมเชื่อว่าคงมี นิสิต/นักศึกษา ที่กำลังปั่นงานของอาจารย์แล้ว search มาเจอ และอยากนำไปใช้ได้โดยเร็ว … ผมขอร้องว่าก่อนจะทิ้งคอมเม็นต์ไว้หรือเมล์มาถาม technical issue กับผม ช่วยศึกษาเรื่องพื้นฐาน C# กับเรื่องพวกวิธี reference รวมถึงอ่าน Readme ก่อน แล้วค่อยถามมานะครับ …

ผมตั้งเป้าไว้ว่าจะมีคนเอาไปใช้ประโยชน์ได้ 2 คนขึ้นไป ใครเอาไปใช้ทำอะไรบอกด้วยๆ :’)

ICU4NET – ICU Binding for .NET

WordBreak

Tags: , , , , , ,

Comments

1.
Zolo Zolo says:

เยี่ยมไปเลยนาย เหมือนว่าเราจะต้องไปนั่งดู​ ICU เหมือนกันอะ ฮา ๆ

2.
Zolo Zolo says:

เยี่ยมไปเลย กำลังจะได้เล่น ICU เลยหละมั้ง ฮาๆ

3.
tot-anusak tot-anusak says:

เป็นงานเป็นการมากมาย O.o

4.
Nuke Nuke says:

ผมเพิ่งรู้เร็วๆนี้เองว่า Java มี BreakIterator ที่ตัดคำได้ที่เอามาจาก ICU ลองเล่นดูใน Java แล้วเหมือนว่ามันใช้ dict ด้วยรึป่าว (อันนี้ไม่รู้) เจอชื่อเฉพาะมันก็ตัดแปลกๆนะ

6.
Bewilder Bewilder says:

เราอ่านแล้วไม่เข้าใจว่าทำไมต้องทำ Binding ทำไมถึงทำเป็น Wrapper ไม่ได้ อะ

7.
m3rlinez m3rlinez says:

@อู๋ IBM Thailand ได้ทำ ICU ด้วยเหรอวะ ดีๆๆ
@โตโต้ ตั้งใจทำกว่าที่บ.อีกนะเนี่ย แอร๊ย ไม่ใช่
@Nuke ใช่แล้วครับ ICU มันใช้ dict ตัดนั่นแหละ ขนาด dict ภาษาไทยประมาณ 500 KB
@อรุช แน่น๊อนนน
@รุต ถ้ามองในแง่ฟังก์ชัน จะ wrap หรือจะทำ binding มันก็ได้เหมือนกันนะ เพียงแต่ถ้าอยากตั้งชื่อโปรเจคว่า ICU4NET (ซึ่งเราอยาก) ตัว interface ข้างใน (classes, methods) มันควรจะเหมือนกับ ICU4C, ICU4J อ่ะ ไม่รู้ตอบตรงคำถามรึเปล่า ?

8.
อรุช อรุช says:

เข้าลิงค์เว็บชาไม่ได้ว่ะ

9.
m3rlinez m3rlinez says:

@อรุช รู้สึกเค้าจะเปลี่ยนชื่อ repo http://github.com/chakrit/fu-sharp

10.
chakrit chakrit says:

Cool Smile

Back where I used to work my friend created an internal database search engine implementation once using Lucene.NET and it can't break thai words - -'

Now it can!

amd thanks for link up on fu# Smile

11.
ob ob says:

ลองเอาไปใช้แล้วใช้ไม่ได้ครับ มันบอก error ว่าไม่เจอ ICU4NET Version=1.0.3716.970 ผมเอา DLL ทั้งหมด ใน Package ที่ Download มาไปไว้ตำแหน่งที่เก็บ EXE แล้วครับ แต่ยังไม่ได้ หรือมีให้ Download ตัวที่เป็น DLL ของ IBM ได้ที่ไหนครับ หรือผมจะดึง Dictionary ที่คุณเอามาใช้ได้จากที่ไหน

12.
m3rlinez m3rlinez says:

คุณ ob ใช้งานโปรแกรมตัวอย่างที่ติดไปได้รึเปล่าครับ ?

13.
ob ob says:

ผมใช้ VS.NET C# 2005 พอลง 2008 ใช้ได้ครับ น่าจะเกี่ยวกับ Version .Net Framework รึเปล่าไม่แน่ใจ แล้วสามารถนำไปใช้กับ VB6 ได้รึเปล่าครับ

14.
333CS 333CS says:

ขอบคุณมากค่ะ  สำหรับบทความนี้ พอดีกำลังทำโปรเจคเรื่องนี้อยู่พอดี  เกี่ยวกับการตรวจสอบคำสะกดบนเวบบอร์ด ได้ลองใช้โปรแกรมที่ให้ไปแล้ว
ว่าจะใข้ vs 2008 เขียน  เป็นไปได้ไหมคะ และควรจะทำอย่างไรบ้าง  ช่วยชี้แนะหน่อยค่ะ

15.
m3rlinez m3rlinez says:

@333CS ใช้ได้แน่นอนครับ แต่ผมแนะนำว่าให้ทำเป็น desktop application (Windows Form หรือ Console app) จะเจอปัญหาน้อยกว่าเอาไปทำเป็น web application

ใช้ class WebClient ให้ไปดึงข้อความมาจากเว็บบอร์ดเรื่อยๆก็ได้ครับ

16.
ob ob says:

ผมลองใช้แล้วมีบางประโยคที่ตัดผิดอยู่ครับ เดี๋ยวเอาให้ดู แล้วอยากทราบว่าเราสามารถเพิ่มคำศัพท์ที่ใช้เปรียบเทียบในการตัดคำได้หรือไม่ครับ

17.
Noomkingkong Noomkingkong says:

ผมอยากเอาไปพัฒนาต่ออ่ะครับ


อยากขอ ซอสโค้ด ต้องติดต่อคุรยยังไง ครับ  บอกทีครัย


นศ วิทยาการคอม ฯ อิอิ

Add comment


(Will show your Gravatar icon)

biuquote
  • Comment
  • Preview
Loading