เป็นปัญหาเดิม ๆ ที่โปรแกรมเมอร์ไทยรู้จักกันดี นั่นคือ การจัดเรียงภาษาไทย เพราะภาษาไทยเป็นภาษาที่ซับซ้อนมาก สระวางได้ตั้งสี่ตำแหน่ง แถมมีวรรณยุกต์ การันต์ ไม้ไต่คู้ (เขียนถูกบ้างหรือเปล่าเนี่ย) และอื่น ๆ อีกมากมาย การจัดเรียงโดยใช้วิธีมาตรฐานเลยมักไม่ได้ผล ก็เลยต้องเขียนวิธีจัดเรียงกันใหม่ ซึ่งในภาษา C พี่เทพ ได้ทำไว้แล้วใน Thai Sorting Algorithms นอกจากนี้ใน Narisa มีคนทำเป็นภาษา PHP ไว้แล้วด้วย ผมคิดว่าเราน่าจะลองทำในภาษาอื่นกันบ้าง (ภาษาอื่น ๆ สนใจเชิญได้ครับ)
ผมขอเริ่มด้วย python ก่อนครับ
#!/usr/bin/python # -*- coding: utf-8 -*- import re def normalize(str_in): regex = re.compile('\xe0\xb9[\x80\x81\x82\x83\x84\x88\x89\x8a\x8b][\w\W][\w\W][\w\W]') pattern = regex.sub('%s', str_in) return pattern%tuple([i[3:]+i[:3] for i in regex.findall(str_in)]) class thstr(str): def __le__(self,s): return normalize(self.__str__()) <= normalize(s) def __lt__(self,s): return normalize(self.__str__()) < normalize(s) def __ge__(self,s): return normalize(self.__str__()) >= normalize(s) def __gt__(self,s): return normalize(self.__str__()) > normalize(s) test = ['บา', 'บ่น', 'บ่า','บ้า','บ้าน','โบว์','ปลา','ปี','แปล'] f = open('out.txt','w') for i in sorted(test): f.write(i+',') f.write('\n') for i in sorted(map(thstr,test)): f.write(i+',') f.close()
ผมใช้วิธี Operation Overriding พวก Operation เปรียบเทียบต่าง ๆ ทำให้เรียกใช้ sort หรือ sorted ได้ทันที แต่ก่อนจะเปรียบเทียบต้อง normalize ก่อน ซึ่งไอ้ normalize นี่แหละยาก ในโปรแกรมที่ผมเขียนครอบคลุมเฉพาะกรณีที่มี วรรณยุกต์ และสระ เ,แ,โ,ไ,ใ เท่านั้น ยังขาดพวกอักษรนำ (เช่น "หมา" ต้องไปเรียงกับ "ม้า" ไม่ใช่ "หา") white space แบบต่าง ๆ และอื่น ๆ อีกมากมาย สนใจร่วมสนุกกันได้ครับ รับรองไม่มีของรางวัล :P
กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น
โอ้ เจ๋ง โชคดีที่ไม่ยุ่งกับภาษาไทย
ไม่เจ๋งหรอกครับ เพราะจริง ๆ ก็เอาแนวคิดมาจากพี่เทพ อีกทั้งยังการ normalize ยังไม่ดีพอ คุณ sugree ไม่สนใจร่วมสนุกหน่อยเหรอครับ แต่ผมว่าเรื่องนี้ขาประจำอย่างคุณ วีร์ น่าจะมีประสบการณ์มากที่สุด
ผมยอมรับว่าไม่เข้าใจภาษาไทยดีพอครับ ยังสับสนกับการเรียงใน unicode กับ ascii ด้วย
ผมเห็นใน perl มี module ช่วยอยู่ตัว
http://search.cpan.org/src/SBURKE/Sort-ArbBiLex-4.01/README
แต่ขี้เกียจลอง perl ก็เลยไปลอง idea ใน java แทน (ดูแล้วน่าจะคล้ายๆกัน)
ปกติใน java มันมี class ที่ช่วยเรื่องพวกนี้อยู่ ชื่อ Collator
ถ้าเขียนแบบไม่ต้องคิดอะไร ก็แบบนี้
อันข้างบน นั่นคือกฎการเรียงที่เขาเตรียมมาให้แล้ว
ถ้าเราจะกำหนดกฎเองก็ได้
ลองดูตัวอย่าง
โห แล้ว RuleBasedCollator นี่มันทำงานยังไงครับ
โอ... สุดยอดครับ เพิ่งรู้เหมือนกันว่า Java สามารถ override method แบบ on the fly ได้ด้วย แถมตัว Comparator ไม่ต้อง override method หลายตัวอีกต่างหาก
ผมมีคำถามเกี่ยวกับ RuleBasedCollator เหมือนกันครับ ว่าเราต้องกำหนด เ,แ,ไ,ใ,โ กับทุกพยัญชนะหรือเปล่า หรือว่าสามารถใช้ RegEx ในการกำหนดได้ด้วย
แล้วก็ค่าที่คืนจาก Comparator.compare() มีค่าอะไรบ้างครับ ในกรณี <, <=, >, >=, ==, !=
เรืองนี้พึ่งศึกษาเหมือนกันครับ
rule ข้างบนนี่นั่งมั่วๆอยู่นานเหมือนกัน (นี่เป็นสาเหตุที่ยังไม่กล้าอธิบายให้คุณสุกรีฟัง)
feature ที่ bow เห็น ใน java เรียกว่า annonymous class
http://www.unix.org.ua/orelly/java-ent/jnut/ch03_12.htm
http://www.developer.com/java/other/article.php/3300881
ดูแล้วก็คล้ายๆ closure, block ของพวก dynamic language เหมือนกัน
http://snakesgemscoffee.blogspot.com/2007/08/anonymous-classes-javas-syn...
เ, แ, ไ, ... เข้าใจว่าใช้ RegEx ไม่ได้นะ
ต้องขยันใส่ทุกตัวอักษร
ค่าที่คืนจาก compare มีค่าได้ดังนี้ -1, 0, 1
กรณี เท่ากัน return 0,
ถ้า left < left return -1
ถ้า left > right return 1