Skip to content

Method .sort #15

@rootEnginear

Description

@rootEnginear

ข้อควรรู้ของ method .sort

  • เป็น method แบบ in place แปลว่ามันจะ sort ตัวแปร/ref เดิมที่เก็บ (มี side effect)
  • เมื่อก่อนมันจะ sort แบบไม่ stable แต่ในปัจจุบัน stable แล้ว

Stable Sort คืออะไร? เวลาเราต้องเรียงข้อมูลหลายอย่าง เช่น ตามชื่อ -> ตามอายุ เรามักจะชินกับการ .sort() หลายๆ รอบ ซึ่งเมื่อก่อน JS sort แบบไม่ Stable แปลว่าชื่อที่เรียงไว้ก่อนอายุมีโอกาสไม่เรียงตามเดิม ทำให้เราต้องเขียน condition ใน sort เยอะๆ

data.sort((a, z) => {
  if (a.age === z.age) return a.name.localeCompare(z.name);
  return a.age - z.age;
});

แต่ในปัจจุบันการ sort ใน JS มัน Stable แล้ว แปลว่าตอนนี้เราทำตามข้างล่างได้แล้ว

data
  .sort((a, z) => a.name.localeCompare(z.name))
  .sort((a, z) => a.age - z.age);

ทำยังไงให้รู้ว่า sort จากน้อยไปมากหรือมากไปน้อย

วิธีง่ายๆ ที่จะทำให้รู้ว่ามันเรียงจากมากไปน้อยหรือน้อยไปมาก คือให้ใช้ params ของ lambda เป็น (a, z)

  • เรียงจากน้อยไปมาก ให้ return เป็น a - z (.sort((a, z) => a - z)) ก็คือเรียงจาก A ไป Z
  • กลับกันถ้าเรียงจากมากไปน้อย ให้ return เป็น z - a (.sort((a, z) => z - a)) ก็คือเรียงจาก Z ไป A

เรียงภาษาไทยให้ถูก

อย่างที่เรารู้ๆ กันว่า ถ้าจะ sort string จากน้อยไปมาก ใช้ .sort() เฉยๆ ก็ได้ หรือใช้ <, > ก็ได้

const data = ['Alex', 'Steve', 'Conner', 'xQc', 'Benjamin'];

// data.sort(); ใช้ได้เหมือนกัน 👍
data.sort((a, z) => {
  if (a < z) return -1; // -1 คือ เอา a ไปวางก่อนหน้า z
  if (a > z) return 1; // 1 คือ เอา a ไปวางหลัง z
  return 0; // 0 คือมันเท่ากัน
});
// -> ['Alex', 'Benjamin', 'Conner', 'Steve', 'xQc']

ดู algorithm ของ SortCompare(x, y) (default) ได้ที่ https://262.ecma-international.org/6.0/#sec-sortcompare

แต่ถ้าเป็นข้อมูลภาษาไทยจะมีโอกาสเรียงผิด เช่น

const data = ['เชษฐา', 'ชัชชาติ', 'สมเกียรติ', 'ไชยวัฒน์', 'เยาว์ลักษณ์'];

data.sort();
// -> ['ชัชชาติ', 'สมเกียรติ', 'เชษฐา', 'เยาว์ลักษณ์', 'ไชยวัฒน์'] ❌
// ต้องเอา `ช` ขึ้นก่อน `ย` และ `ย` ต้องอยู่ก่อน `ส` ด้วย

วิธีแก้คือ ให้ใช้ <string>.localeCompare(<string>)

const data = ['เชษฐา', 'ชัชชาติ', 'สมเกียรติ', 'ไชยวัฒน์', 'เยาว์ลักษณ์'];

data.sort((a,z) => a.localeCompare(z));
// -> ['ชัชชาติ', 'เชษฐา', 'ไชยวัฒน์', 'เยาว์ลักษณ์', 'สมเกียรติ'] ✅

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions