JavaScript
Array Methods
sort
เรียนรู้ sort() — method เรียงลำดับ element ใน array แบบเปลี่ยนต้นฉบับ (mutating) ตั้งแต่ default sort ที่เรียงแบบ string (UTF-16) ซึ่งทำให้ [3,20,100] → [100,20,3], compareFunction ที่ใช้ arrow function (a,b)=>a-b เรียงน้อยไปมาก และ (a,b)=>b-a เรียงมากไปน้อย, การ copy ก่อน sort ด้วย concat(), ไปจนถึงการใช้ sort() ในสถานการณ์จริง เช่น เรียงราคาสินค้า คะแนนสอบ และใช้ร่วมกับ indexOf/includes ผ่าน Lab 3 ข้อ
`sort()` คืออะไร — เรียงลำดับ element และเปลี่ยนต้นฉบับ
sort() เป็น method ใน array ใช้เรียงลำดับ (sort) element ใน array — เรียงจากน้อยไปมากตามกฎที่กำหนด และเปลี่ยนต้นฉบับโดยตรง สิ่งที่ต้องรู้: • sort() เป็น mutating method — **เปลี่ยน array ต้นฉบับ** เช่นเดียวกับ reverse() • sort() คืนค่า (return) array ที่เรียงแล้ว — เป็น reference ของ array ต้นฉบับ • sort() รับ argument ได้ 1 ตัว คือ compareFunction (ไม่บังคับ) • ถ้าไม่ใส่ compareFunction — element จะถูกแปลงเป็น string แล้วเรียงตาม UTF-16 code unit order ⚠️ คำเตือนสำคัญ: sort() แบบไม่ใส่ compareFunction เรียงแบบ string — ไม่ใช่ numeric — ทำให้ [3, 20, 100].sort() ได้ [100, 20, 3] เพราะ "100" < "20" < "3" เมื่อเทียบแบบ string
const fruits = ["banana", "apple", "cherry"];
// sort() แบบ default — เรียง string ตาม alphabet
fruits.sort();
console.log(fruits); // ["apple", "banana", "cherry"]
// เรียง A-Z ✓ — เพราะเป็น string ทั้งหมด
const numbers = [3, 20, 100];
// sort() แบบ default — element ถูกแปลงเป็น string!
numbers.sort();
console.log(numbers); // [100, 20, 3] ← ไม่ใช่ 3, 20, 100! ⚠️
// เพราะ "100" < "20" < "3" เมื่อเทียบแบบ string (ดูทีละตัวอักษร)
sort() แบบ default แปลง element เป็น string แล้วเทียบทีละตัวอักษร — "1" มาก่อน "2" มาก่อน "3" — ไม่ใช่เรียงตามค่าตัวเลข
กฎสำคัญ: • sort() เรียงแบบ string (lexicographic / dictionary order) โดย default • ตัวเลขทุกตัวจะถูกแปลงเป็น string ก่อนเทียบ — "100" มาก่อน "20" เพราะ '1' < '2' • ถ้าต้องการเรียงตัวเลขตามค่าจริง ต้องใช้ compareFunction — หัวข้อถัดไปจะสอน
sort() แบบ default — เรียงตาม string และ UTF-16 code unit
sort() แบบ default เรียงตาม code unit ใน UTF-16 — ซึ่งตรงกับลำดับใน dictionary สำหรับตัวอักษรภาษาอังกฤษส่วนใหญ่ แต่มีจุดที่ต้องระวัง: พฤติกรรม default sort: • ตัวพิมพ์ใหญ่ (A-Z) มาก่อนตัวพิมพ์เล็ก (a-z) — เพราะ code point ของ 'A' (65) < 'a' (97) • ตัวเลขเรียงตาม string — "1" ก่อน "2" ก่อน "3" ... แต่วิธีนี้ทำให้ "100" < "20" • ภาษาไทยเรียงตาม code point ซึ่งไม่ตรงกับพจนานุกรมไทย — 'ก' (0E01) < 'ข' (0E02) ใช้ได้ แต่การเรียงเสียงวรรณยุกต์อาจไม่ตรงตามที่คาด
const words = ["apple", "Banana", "cherry", "Apple"];
words.sort();
console.log(words);
// ["Apple", "Banana", "apple", "cherry"]
// A (65), B (66) มาก่อน a (97), c (99)
// === เรียงชื่อภาษาอังกฤษ — ใช้ default sort ได้เลย
const names = ["Charlie", "Alice", "Bob", "David"];
names.sort();
console.log(names); // ["Alice", "Bob", "Charlie", "David"] ✓
// === เรียงลำดับ string ที่มีแต่ตัวอักษร — ใช้ default sort ได้
const tags = ["html", "css", "javascript"];
tags.sort();
console.log(tags); // ["css", "html", "javascript"] ✓
// === เรียงตัวเลข — default sort ไม่เหมาะ → ต้องใช้ compareFunction
const scores = [10, 2, 100, 50];
scores.sort();
console.log(scores); // [10, 100, 2, 50] ← เรียงแบบ string ไม่ใช่ตัวเลข
สรุป: default sort ใช้ได้ดีกับ array ที่มีแต่ string ภาษาอังกฤษ — แต่ถ้าอยากเรียงตัวเลข หรือเรียงแบบกำหนดเอง ต้องใช้ compareFunction
compareFunction — กำหนดกฎการเรียงลำดับด้วยตัวเอง
compareFunction เป็น callback function ที่ sort() เรียกใช้เมื่อต้องการเทียบ element สองตัว — โดยรับ a กับ b เป็น parameter แล้ว return ค่าเป็นตัวเลขเพื่อบอกว่าใครควรมาก่อน กฎของ compareFunction(a, b): • return **ค่าติดลบ (< 0)** → a มาก่อน b • return **0** → ลำดับไม่เปลี่ยน (a กับ b เท่ากัน) • return **ค่าบวก (> 0)** → a มาหลัง b วิธีจำง่าย ๆ: อยากให้ a มาก่อน b → return a - b (ถ้า a < b จะได้ค่าติดลบ) เราใช้ arrow function `(a, b) => a - b` เพราะ: • a < b เช่น a=30, b=40 → 30 - 40 = -10 (ติดลบ) → a มาก่อน b ✓ • a > b เช่น a=40, b=30 → 40 - 30 = 10 (บวก) → a มาหลัง b ✓ • a === b → 0 → ลำดับไม่เปลี่ยน ✓
const scores = [85, 42, 99, 67, 23];
// เรียงจากน้อยไปมาก (ascending) — ใช้ (a, b) => a - b
scores.sort((a, b) => a - b);
console.log(scores); // [23, 42, 67, 85, 99] ✓
// === ทีละขั้น: sort() เรียก compareFunction หลายครั้ง
// compare(85, 42) → 85-42=43 (บวก) → 85 ไปหลัง 42 → [42, 85, 99, 67, 23]
// compare(85, 99) → 85-99=-14 (ลบ) → 85 อยู่ก่อน 99 → [42, 85, 99, 67, 23]
// compare(99, 67) → 99-67=32 (บวก) → 99 ไปหลัง 67 → [42, 85, 67, 99, 23]
// ...ไปเรื่อย ๆ จนเรียงเสร็จ
const prices = [150, 50, 300, 200, 100];
// เรียงจากมากไปน้อย (descending) — ใช้ (a, b) => b - a
prices.sort((a, b) => b - a);
console.log(prices); // [300, 200, 150, 100, 50] ✓
// === วิธีคิด: b - a
// a=50, b=150 → 150-50=100 (บวก) → 150 มาก่อน 50 เพราะ b > a
// a=300, b=50 → 50-300=-250 (ลบ) → 300 มาก่อน 50 เพราะ a > b
// → ผลลัพธ์: ตัวใหญ่มาก่อน ✓
// === ใช้ function declaration หรือ function expression ก็ได้
function sortDesc(a, b) {
return b - a;
}
const nums = [1, 5, 3, 9, 2];
nums.sort(sortDesc);
console.log(nums); // [9, 5, 3, 2, 1]
เปรียบเทียบ compareFunction 3 แบบที่ใช้บ่อย: • `(a, b) => a - b` — เรียงตัวเลขน้อย→มาก (ascending) • `(a, b) => b - a` — เรียงตัวเลขมาก→น้อย (descending) • ไม่ใส่ compareFunction — เรียงแบบ string (default)
ใช้ `sort()` ในสถานการณ์จริง
sort() ใช้บ่อยมากในงานจริง — เรียงสินค้าตามราคา, เรียงคะแนน, เรียงชื่อ, เรียงวันที่, หรือเรียงข้อมูลก่อนแสดงผล สถานการณ์ที่ใช้ sort(): • เรียงคะแนนสอบจากสูงสุดไปต่ำสุด • เรียงรายการสินค้าจากถูกไปแพง • เรียงชื่อพนักงานตาม alphabet • เรียงข้อมูลตามลำดับความสำคัญก่อนแสดงใน UI เทคนิค: ใช้ concat().sort() เมื่อต้องการเก็บ array ต้นฉบับไว้โดยไม่เปลี่ยน
// === เรียงคะแนนสอบ — มาก→น้อย (descending)
const scores = [78, 92, 85, 67, 95, 88];
// copy ก่อน sort ถ้าต้องการเก็บต้นฉบับ
const ranked = scores.concat().sort((a, b) => b - a);
console.log("อันดับ (มาก→น้อย):", ranked);
// [95, 92, 88, 85, 78, 67]
console.log("คะแนนเดิม:", scores);
// [78, 92, 85, 67, 95, 88] ← ต้นฉบับไม่เปลี่ยน ✓
// === เรียงราคาสินค้า — น้อย→มาก (ascending)
const prices = [450, 120, 890, 350, 99];
prices.sort((a, b) => a - b);
console.log("ราคา (ถูก→แพง):", prices);
// [99, 120, 350, 450, 890]
// === ใช้ sort() ร่วมกับ reverse() เพื่อเรียงจากแพง→ถูก
const products = [450, 120, 890, 350, 99];
products.sort((a, b) => a - b); // น้อย→มาก
products.reverse(); // กลับ → มาก→น้อย
console.log("ราคา (แพง→ถูก):", products);
// [890, 450, 350, 120, 99]
// === เรียงชื่อตาม alphabet (default sort ก็พอ)
const students = ["สมชาย", "กานดา", "วิชัย", "บุญมี"];
students.sort();
console.log(students);
// เรียงตาม code point ของอักษรไทย
// === เรียง string ที่มี prefix ตัวเลข
const files = ["file10.txt", "file2.txt", "file1.txt"];
files.sort(); // default string sort
console.log(files);
// ["file1.txt", "file10.txt", "file2.txt"] ← "1" < "10" < "2" แบบ string
sort() ทำงานร่วมกับ method อื่นที่เราเรียนมาแล้วได้ดี: • concat().sort() — copy แล้วเรียง โดยไม่เปลี่ยนต้นฉบับ • sort().reverse() — เรียงน้อย→มาก แล้วกลับเป็นมาก→น้อย (หรือใช้ compareFunction แบบ b-a ก็ได้) • indexOf() หลัง sort — หาตำแหน่งใหม่ของ element หลังเรียง • includes() หลัง sort — ตรวจสอบว่า element ยังอยู่
จุดที่มือใหม่มักพลาด
- default sort เรียงแบบ string ไม่ใช่ numeric — `[3, 20, 100].sort()` → `[100, 20, 3]` — ไม่ใช่ `[3, 20, 100]` — มือใหม่เกือบทุกคนพลาดตรงนี้
- ลืมใส่ compareFunction เวลาเรียงตัวเลข — แล้วได้ผลลัพธ์ผิดโดยไม่รู้ตัว — เช็กเสมอว่าคุณใช้ `(a, b) => a - b` หรือเปล่า
- sort() เปลี่ยนต้นฉบับ — `arr.sort()` เปลี่ยน arr เลย — ถ้าต้องการเก็บต้นฉบับไว้ ใช้ `arr.concat().sort()`
- compareFunction return ค่าติดลบ บวก ศูนย์ — ไม่ใช่ boolean — `(a, b) => a > b` ไม่ได้ผลตามที่คิด (return true/false ไม่ใช่ negative/zero/positive)
- เรียง string ภาษาไทย — default sort เรียงตาม code point (UTF-16) — อาจไม่ตรงตามพจนานุกรมไทยเมื่อมีสระและวรรณยุกต์ที่ซับซ้อน — ในขั้นนี้แค่รู้ว่าใช้ default sort กับไทยได้ระดับหนึ่งก็พอ
- sort() กับ empty array หรือ single element — ไม่ error — `[].sort()` → `[]`, `["a"].sort()` → `["a"]` — ปกติดี
- ใช้ sort() ซ้อนกันโดยไม่ตั้งใจ — เช่น `arr.sort().sort()` — sort สองครั้งอาจไม่เกิดผลเพิ่ม เพราะเรียงแล้วครั้งแรกก็เรียงอยู่แล้ว