บทความทั้งหมด

Text Diff: อัลกอริทึมหาความแตกต่างของข้อความทำงานอย่างไร

ภาษาไทยเขียนติดกันไปทั้งประโยคโดยไม่มีการเว้นวรรคระหว่างคำ เช่น "ไปโรงเรียนด้วยกัน" ไม่มีเครื่องหมายใดบอกว่าคำแต่ละคำแบ่งตรงไหน ต้องอาศัยการตัดคำ (word segmentation) ด้วยพจนานุกรมหรือโมเดลภาษาช่วยเดา — ด้วยเหตุนี้ diff ระดับคำในภาษาไทยจึงมีความกำกวมโดยธรรมชาติ ในขณะที่ diff ระดับอักขระกลับให้ผลที่ตรงไปตรงมากว่า เพราะไม่ต้องเดาขอบเขตคำเลย

Longest Common Subsequence

วิธี diff แบบคลาสสิกอิงจากการหา longest common subsequence (LCS) ของบรรทัดระหว่างข้อความสองเวอร์ชัน บรรทัดที่เป็นส่วนหนึ่งของ subsequence นี้ถือว่าไม่เปลี่ยนแปลง ส่วนที่เหลือจะถูกทำเครื่องหมายว่าถูกลบจากเวอร์ชันเก่าหรือเพิ่มในเวอร์ชันใหม่ วิธีนี้ให้ชุดการเปลี่ยนแปลงที่น้อยที่สุด ไม่ใช่ลำดับการลบและเพิ่มแบบใดก็ได้ที่บังเอิญใช้ได้

วิธีอ่านผลลัพธ์

บรรทัดที่ถูกลบมักถูกทำเครื่องหมายด้วย - สีแดง ส่วนบรรทัดที่เพิ่มด้วย + สีเขียว บรรทัดที่ "เปลี่ยนแปลง" ในความหมายทั่วไป ในทางเทคนิคจะแสดงเป็นการลบบรรทัดเก่าบวกกับการเพิ่มบรรทัดใหม่ — diff ไม่มีแนวคิดของการแก้ไขบรรทัดในตำแหน่งเดิมโดยตรง

ทำไมการเปรียบเทียบแบบบรรทัดต่อบรรทัดไม่ได้ตรงใจเสมอไป

หากมีการแทรกบรรทัดใหม่เข้าไปกลางข้อความ การเปรียบเทียบแบบบรรทัดต่อบรรทัดอาจแสดงว่าบรรทัดถัดไปทั้งหมด "เปลี่ยนแปลง" — เพราะอัลกอริทึมไม่ได้แยกแยะได้เสมอว่านี่คือการแทรกหรือการแทนที่จำนวนมาก สำหรับข้อความภาษาไทย ปัญหานี้ซับซ้อนขึ้นอีกชั้นในระดับคำ เพราะไม่มีขอบเขตคำที่ชัดเจนให้ diff อ้างอิงตั้งแต่แรก

ทำไมต้องใช้สิ่งนี้

  • ดูให้แน่ชัดว่ามีอะไรเปลี่ยนแปลงระหว่างไฟล์การตั้งค่าหรือเอกสารสองเวอร์ชัน
  • รีวิวโค้ดโดยเข้าใจตรรกะของอัลกอริทึมหาความแตกต่าง
  • เปรียบเทียบผลลัพธ์ของสคริปต์ก่อนและหลัง refactoring เพื่อให้แน่ใจว่าไม่มี regression

Diff ระดับบรรทัดกับระดับอักขระ

การเปรียบเทียบทีละบรรทัดเหมาะกับโค้ดและไฟล์ตั้งค่า แต่สำหรับข้อความร้อยแก้วหรือประโยคยาวที่มีเพียงคำเดียวเปลี่ยนไป มันจะทำเครื่องหมายทั้งบรรทัดว่าถูกลบและเพิ่มใหม่ สำหรับภาษาไทยโดยเฉพาะ diff ระดับอักขระมักให้ผลที่นำไปใช้ได้จริงมากกว่า diff ระดับคำ เพราะไม่ต้องพึ่งการตัดคำที่อาจผิดพลาดได้

ลองใช้เครื่องมือ