JavaScript
Arrays
Nested arrays
เรียนรู้ Nested Array (array ซ้อน array) ตั้งแต่การสร้าง array 2 มิติ, การเข้าถึง element ด้วย [][], การอัปเดตและเพิ่มข้อมูลใน nested array, การวนลูปด้วย nested for loop, ไปจนถึงการใช้งานจริง เช่น ผังที่นั่ง, ตารางคะแนน, และกระดานเกม ผ่าน Lab 5 ข้อที่ไล่ระดับจากสร้างและอ่าน สู่ประยุกต์ใช้
Nested Array คืออะไร — Array เก็บ Array ไว้ข้างใน
ที่ผ่านมาเราใช้ array เก็บข้อมูลแบบแถวเดียว (1 มิติ) เช่น `["สมชาย", "สมหญิง", "สมปอง"]` — ทุก element คือค่าเดี่ยว ๆ **Nested Array** (หรือ Multi-dimensional Array) คือ array ที่ element บางตัวเป็น **array อีกตัวหนึ่ง** — ทำให้เราจัดข้อมูลเป็นแถวเป็นคอลัมน์ได้เหมือนตาราง นิยมใช้กับ: • ตารางข้อมูล (ตารางคะแนน, ตารางราคา) • กระดานเกม (หมากรุก, OX) • ผังที่นั่ง • พิกัด (x, y) หรือ (row, col) ตัวอย่างด้านล่างเป็น nested array 2 มิติ — แถวนอนคือ row, แถวตั้งคือ col
Nested Array 2 มิติ: แต่ละ row เป็น array ด้านนอก index (0,1,2) และแต่ละ col เป็น index ด้านใน — วิธีคิดเหมือนตาราง row × col
// === Nested Array 2 มิติ (3 แถว × 3 คอลัมน์) ===
const matrix = [
[1, 2, 3], // row 0 — มี 3 element
[4, 5, 6], // row 1
[7, 8, 9], // row 2
];
console.log(matrix);
// [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
console.log("จำนวนแถว:", matrix.length); // 3
console.log("จำนวนคอลัมน์ในแถวแรก:", matrix[0].length); // 3
// === Nested Array 3 มิติ (แค่รู้ไว้ — ไม่ต้องใช้บ่อย) ===
const cube = [
[[1, 2], [3, 4]],
[[5, 6], [7, 8]],
];• `matrix.length` = 3 — คือจำนวนแถว (row) • `matrix[0].length` = 3 — คือจำนวนคอลัมน์ในแถวแรก • แต่ละ `matrix[i]` คือ array ทั้งแถว — เช่น `matrix[0]` คือ `[1, 2, 3]` • Nested array ไม่จำเป็นต้องมีขนาดเท่ากันทุกแถว — JavaScript ไม่บังคับ — แต่ในทางปฏิบัติเรามักทำให้เท่ากันเพื่อความเป็นระเบียบ วิธีมอง: nested array 2 มิติ = ตาราง 2 ชั้น — index ตัวแรกเลือกแถว, index ตัวที่สองเลือกคอลัมน์ในแถวนั้น
เข้าถึง Element ใน Nested Array — ใช้ `[]` สองชั้น
การอ่านค่าใน nested array ใช้ bracket notation ซ้อนกัน — `arr[row][col]` • `arr[row]` — เข้าถึงแถวที่ row (ได้ array ทั้งแถว) • `arr[row][col]` — เข้าถึง element ในแถวที่ row, คอลัมน์ที่ col index ทั้ง row และ col เริ่มที่ 0 เหมือน array ปกติ
const matrix = [
[1, 2, 3], // row 0
[4, 5, 6], // row 1
[7, 8, 9], // row 2
];
// col 0,1,2
// อ่านค่าในแถวเดียวกัน ก่อน
console.log(matrix[0]); // [1, 2, 3] — array ทั้งแถว
console.log(matrix[1]); // [4, 5, 6]
// อ่านค่าเฉพาะจุด — arr[row][col]
console.log(matrix[0][0]); // 1 — แถว 0, คอลัมน์ 0
console.log(matrix[0][1]); // 2 — แถว 0, คอลัมน์ 1
console.log(matrix[1][2]); // 6 — แถว 1, คอลัมน์ 2
console.log(matrix[2][0]); // 7 — แถว 2, คอลัมน์ 0
// ตรงกลาง — แถว 1, คอลัมน์ 1
console.log(matrix[1][1]); // 5// === Flat Array (1 มิติ) — 1 index ===
const flat = [10, 20, 30, 40, 50, 60, 70, 80, 90];
console.log(flat[4]); // 50 — index เดียว
// === Nested Array (2 มิติ) — 2 index ===
const nested = [
[10, 20, 30], // row 0
[40, 50, 60], // row 1
[70, 80, 90], // row 2
];
console.log(nested[1][1]); // 50 — แถว 1, คอลัมน์ 1
// flat[4] เดียว = nested[1][1]
// === อ่านทั้งแถว vs อ่านค่าเดียว ===
const row1 = nested[1]; // [40, 50, 60] — array ทั้งแถว
const cell1 = nested[1][0]; // 40 — เฉพาะค่าเดียว
console.log(row1); // [40, 50, 60]
console.log(cell1); // 40กฎสำคัญ: • `arr[row]` ได้ array ทั้งแถว — เอาไปใช้ต่อได้เหมือน array ปกติ • `arr[row][col]` ได้ค่าเดี่ยว — ใช้ตอนอยากได้ element เป๊ะ ๆ • index เกินขอบเขตจะได้ undefined — `matrix[3]` หรือ `matrix[0][5]` จะเป็น undefined — ไม่ error
อัปเดตและแก้ไข Element ใน Nested Array
การแก้ค่า element ใน nested array ทำได้ด้วย `arr[row][col] = newValue` — หลักการเดียวกับการอัปเดต array ปกติ แต่ใช้ bracket ซ้อนสองชั้น และเพราะ nested array ก็คือ array ปกติ — method ต่าง ๆ อย่าง `push()`, `splice()`, `sort()` ใช้ได้กับ array ชั้นในเหมือนเดิม
const scoreTable = [
[85, 90, 78],
[92, 88, 95],
[76, 84, 80],
];
// อัปเดตคะแนนสมมติ — แก้แถว 0 คอลัมน์ 2
scoreTable[0][2] = 82;
console.log(scoreTable[0]); // [85, 90, 82] ← เปลี่ยนแล้ว
// แก้แถว 2 คอลัมน์ 0
scoreTable[2][0] = 79;
console.log(scoreTable[2]); // [79, 84, 80]
// ตรวจสอบทั้งหมด
console.log(scoreTable);
// [ [85, 90, 82], [92, 88, 95], [79, 84, 80] ]const table = [
[1, 2, 3],
[4, 5, 6],
];
// === เพิ่มแถวใหม่ทั้งแถว — push เข้า array นอก ===
table.push([7, 8, 9]);
console.log(table);
// [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
// === เพิ่ม element ใหม่ในแถวที่มีอยู่ — push เข้า array ใน ===
table[0].push(99);
console.log(table[0]); // [1, 2, 3, 99]
// === แก้ไขทั้งแถว — assign array ใหม่เข้าไป ===
table[1] = [40, 50, 60];
console.log(table[1]); // [40, 50, 60]
// === ลบแถวท้าย — pop จาก array นอก ===
table.pop();
console.log(table);
// [ [1, 2, 3, 99], [40, 50, 60] ]ข้อสังเกต: • `table.push([...])` — เพิ่มแถวใหม่ทั้งแถว (เพิ่มใน array นอก) • `table[i].push(...)` — เพิ่ม element ในแถวที่มีอยู่ (เพิ่มใน array ใน) • `table.pop()` — ลบแถวท้าย (ลบจาก array นอก) • `table[i].pop()` — ลบ element สุดท้ายของแถวนั้น (ลบจาก array ใน) • `table[i] = [...]` — แทนที่ทั้งแถว วิธีจำ: นึกว่า array นอกคือ list ของแถว, array ในคือ list ของ element ในแต่ละแถว — เลือกใช้ method ตามชั้นที่ต้องการจัดการ
วนลูป Nested Array — ใช้ `for` ซ้อน `for`
การวนลูป nested array ใช้ **nested for loop** — for ตัวนอกวนตามแถว (row), for ตัวในวนตามคอลัมน์ (col) ภายในแต่ละแถว รูปแบบมาตรฐาน: • for ตัวนอก: `for (let i = 0; i < arr.length; i++)` — วนแถว • for ตัวใน: `for (let j = 0; j < arr[i].length; j++)` — วนคอลัมน์ในแถว i • เข้าถึง element ด้วย `arr[i][j]` เทคนิคสำคัญ: `arr[i].length` — เพราะแถวอาจยาวไม่เท่ากัน — ใช้ length ของแถวนั้นโดยตรงดีกว่าใช้ค่าคงที่
const grid = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
// for ตัวนอก — วนตามแถว
for (let i = 0; i < grid.length; i++) {
// สร้าง string เก็บค่าทั้งแถว
let row = "";
// for ตัวใน — วนตามคอลัมน์ในแถว i
for (let j = 0; j < grid[i].length; j++) {
row += grid[i][j] + " ";
}
console.log("Row " + i + ":", row.trim());
}
// Row 0: 1 2 3
// Row 1: 4 5 6
// Row 2: 7 8 9const scores = [
[85, 90, 78],
[92, 88, 95],
[76, 84, 80],
];
let total = 0;
let count = 0;
// วน nested for loop
for (let i = 0; i < scores.length; i++) {
for (let j = 0; j < scores[i].length; j++) {
total = total + scores[i][j];
count = count + 1;
}
}
console.log("ผลรวม:", total); // 768
console.log("จำนวน element:", count); // 9
console.log("ค่าเฉลี่ย:", total / count); // 85.333...เทคนิคการใช้งาน nested for loop กับ 2D array: • แสดงผลเป็นตาราง — วน i (แถว) แล้ววน j (คอลัมน์) ในแต่ละ i • หาผลรวม / ค่าเฉลี่ย — accumulate ในตัวแปรนอก loop • หาค่าสูงสุด / ต่ำสุด — เปรียบเทียบ `grid[i][j]` กับค่าที่เก็บไว้ • นับจำนวนตามเงื่อนไข — เพิ่ม counter ตอนเจอค่าที่ต้องการ ก่อนใช้ nested for loop ให้มั่นใจว่าเข้าใจ for loop พื้นฐานดีแล้ว — ถ้าต้องการทวน for loop กลับไปบทที่ 27 (for loop) ก่อนได้
Nested Array ในชีวิตจริง
Nested array ใช้ได้ในหลายสถานการณ์จริง — ตารางข้อมูล ผังที่นั่ง กระดานเกม หรือพิกัด หัวข้อนี้จะแสดงตัวอย่างการใช้งาน nested array ในโจทย์ที่ใกล้เคียงของจริง — เพื่อให้เห็นวิธีคิดและวิธีใช้มากกว่าแค่ syntax
// 0 = ว่าง, 1 = จองแล้ว
const seats = [
[0, 1, 0], // แถว A — A1:ว่าง, A2:จอง, A3:ว่าง
[0, 0, 1], // แถว B
[1, 0, 0], // แถว C
];
// เช็กที่นั่ง B2 (row=1, col=1)
if (seats[1][1] === 0) {
console.log("B2: ว่าง");
} else {
console.log("B2: จองแล้ว");
}
// แสดงแผนผัง
for (let i = 0; i < seats.length; i++) {
let rowDisplay = "";
for (let j = 0; j < seats[i].length; j++) {
rowDisplay += seats[i][j] === 0 ? "◻ " : "◼ ";
}
console.log(rowDisplay);
}
// ◻ ◼ ◻
// ◻ ◻ ◼
// ◼ ◻ ◻// 3 นักเรียน × 3 วิชา
const scores = [
[85, 90, 78], // นักเรียน 1: คะแนนวิชา A, B, C
[92, 88, 95], // นักเรียน 2
[76, 84, 80], // นักเรียน 3
];
const names = ["สมชาย", "สมหญิง", "สมปอง"];
// === หาค่าเฉลี่ยของนักเรียนแต่ละคน ===
for (let i = 0; i < scores.length; i++) {
let sum = 0;
for (let j = 0; j < scores[i].length; j++) {
sum = sum + scores[i][j];
}
let avg = sum / scores[i].length;
console.log(names[i] + ":", avg);
}
// สมชาย: 84.33333333333333
// สมหญิง: 91.66666666666667
// สมปอง: 80
// === หาค่าเฉลี่ยแต่ละวิชา (คอลัมน์) ===
for (let j = 0; j < 3; j++) {
let sum = 0;
for (let i = 0; i < scores.length; i++) {
sum = sum + scores[i][j];
}
console.log("วิชา " + (j + 1) + ":", sum / scores.length);
}
// วิชา 1: 84.33333333333333
// วิชา 2: 87.33333333333333
// วิชา 3: 84.33333333333333const board = [
["X", "O", "X"],
["O", "X", "O"],
["X", "O", "X"],
];
// === เช็กผู้ชนะแนวนอน — row 0 ===
let row = 0;
if (board[row][0] === board[row][1] && board[row][1] === board[row][2]) {
console.log(board[row][0] + " ชนะในแถว " + row);
} else {
console.log("แถว " + row + ": ไม่มีผู้ชนะ");
}
// แถว 0: ไม่มีผู้ชนะ
// === เช็กผู้ชนะแนวตั้ง — col 1 ===
let col = 1;
if (board[0][col] === board[1][col] && board[1][col] === board[2][col]) {
console.log(board[0][col] + " ชนะในคอลัมน์ " + col);
} else {
console.log("คอลัมน์ " + col + ": ไม่มีผู้ชนะ");
}
// คอลัมน์ 1: O ชนะในคอลัมน์ 1
// === เช็กแนวทแยง ===
if (board[0][0] === board[1][1] && board[1][1] === board[2][2]) {
console.log(board[0][0] + " ชนะแนวทแยง!");
} else {
console.log("แนวทแยงหลัก: ไม่มีผู้ชนะ");
}
// แนวทแยงหลัก: X ชนะแนวทแยง!ตัวอย่างเหล่านี้คือการนำ nested array ไปใช้แก้โจทย์จริง — ผังที่นั่ง ตารางคะแนน กระดานเกม — ทุกตัวอย่างใช้แค่ `arr[row][col]` และ `for` loop ซ้อนกัน pattern หลักที่ใช้ตลอดคือ: • `arr[i][j]` — เข้าถึง element • nested for loop — วน loop ทั้ง 2 มิติ • `if/else` — ตรวจสอบเงื่อนไขตามค่าในตำแหน่งต่าง ๆ
จุดที่มือใหม่มักพลาด
- index นอกหลุด — `arr[3]` เมื่อมีแค่ 3 แถว (index 0-2) → ได้ undefined → พอใช้ `arr[3][0]` จะ error `Cannot read properties of undefined`
- index ในหลุด — `arr[0][3]` เมื่อแถวมี 3 element (index 0-2) → ได้ undefined — ไม่ error แต่อาจทำให้逻辑ผิด
- แถวยาวไม่เท่ากัน — `arr[i].length` กับ `arr[i+1].length` อาจไม่เท่ากัน — ใช้ `arr[i].length` ใน for ตัวในเสมอ อย่าใช้ค่าคงที่
- ลืม nested for loop — สำหรับ 2D array ต้องใช้ for ซ้อน for — for ตัวเดียววนทั้ง row และ col ไม่ได้ — ถ้าต้องการวนทุก element ต้องมี 2 ชั้น
- ใช้ method ผิดชั้น — `arr.push()` เพิ่มแถว, `arr[i].push()` เพิ่ม element ในแถว — อย่าสลับกัน เช่นจะเพิ่มคะแนนในแถวนึงแต่ใช้ `scores.push()` จะได้เพิ่มแถวใหม่แทน
- row vs col สลับกัน — `arr[0][1]` ≠ `arr[1][0]` — แถวกับคอลัมน์ไม่เหมือนกัน — ตรวจสอบเสมอว่า index ตัวแรกคือ row (แถวนอน) และ index ตัวที่สองคือ col (คอลัมน์)
- splice กับ nested array — `arr.splice()` ลบ/เพิ่มแถว (ของ array นอก), `arr[i].splice()` ลบ/เพิ่ม element ในแถวนั้น — ใช้ splice ตอน nested array ระวังเรื่องชั้น
- console.log nested array — ถ้าอยากดู element ควรใช้ nested for loop แสดงทีละตัว แทนที่จะ console.log ทั้งก้อน — การดูทีละตัวทำให้เจอจุดผิดง่ายกว่า