ในบทที่แล้วได้แนะนำให้รู้จักสิ่งที่เรียกว่า
แถวลำดับ (array)
ไป
ในบทนี้จะแนะนำการจัดการอะไรต่างๆภายในแถวลำดับ
นอกเหนือจากที่แนะนำไปในเบื้องต้นแล้ว
ตัวดำเนินการเมื่อใช้กับแถวลำดับ
หากนำแถวลำดับมาบวกกันเองหรือไปบวกกับข้อมูลชนิดอื่น
แถวลำดับจะถูกแปลงเป็นสายอักขระแล้วเอาไปต่อกับอีกตัวที่มาบวกด้วย
ลักษณะเมื่อแปลงเป็นสายอักขระจะมีลักษณะเหมือนกับเมื่อใช้ alert เพื่อแสดงผล
ปกติเมื่อนำแถวลำดับไปแสดงผลโดยใช้คำสั่งเช่น alert
จะเห็นว่าข้อมูลทั้งหมดในนั้นถูกรวมเชื่อมติดกันโดยคั่นด้วยจุลภาค
และไม่มีการแสดงเครื่องหมายคำพูด แม้ว่าจะเป็นข้อมูลชนิดสายอักขระ
การแสดงผลแบบเดียวกันนี้ยังเกิดขึ้นเมื่อมีการนำไปบวกกับข้อมูลชนิดอื่นด้วย
คือเมื่อไปบวกจะกลายเป็นการแปลงเป็นสายอักขระแล้วก็เอาไปต่อกับอีกตัว
ตัวอย่าง
alert(["ก"] + "1"); // ได้ ก1
alert([1, "2"] + 3); // ได้ 1,23
alert([4] + 4); // ได้ 44
alert([5,6] + [7,8]); // ได้ 5,67,8
นอกจากเครื่องหมายบวกแล้ว เมื่อใช้เครื่องหมาย - * / %
หากแถวลำดับนั้นมีสมาชิกอยู่แค่ตัวเดียวจะกลายเป็นการนำสมาชิกตัวเดียวนั้นมาแปลงเป็นตัวเลขแล้วเข้าตัวดำเนินการ
alert(["3"] - "5"); // ได้ 2
alert([4] - 3); // ได้ 1
ถ้าแถวลำดับมีสมาชิกมากกว่าหนึ่งตัวจะได้ NaN เสมอ
หรือถ้าเป็นตัวที่ไม่สามารถแปลงเป็นตัวเลขได้ก็ได้ NaN เช่นกัน
alert(["ส"] - "8"); // ได้ NaN
alert([11, 12] - 7); // ได้ NaN
การเชื่อมรวมสมาชิกในแถวลำดับ
หากต้องการเอาข้อมูลทั้งหมดในแถวลำดับมาต่อกันสามารถใช้เมธอด .join
วิธีใช้
แถวลำดับ.join(ตัวเชื่อม)
ตัวอย่าง
var ar = ["python", "ruby", "java"];
alert(ar.join(" กับ ")); // ได้ python กับ ruby กับ java
alert([1, 2, 3, 4].join(0)); // ได้ 1020304
alert([1, 2, 3, 4].join()); // ได้ 1,2,3,4
ถ้าไม่ใส่ตัวเชื่อม จะได้จุลภาค , เป็นตัวเชื่อม
การหาค่าสูงสุดต่ำสุดในแถวลำดับ
หลักการหาค่าสูงสุดหรือต่ำสุดของสมาชิกที่อยู่ภายในแถวลำดับนั้น
อาจลองเปรียบเทียบกับนายพรานที่ไปล่ากลางเพื่อทำเป็นอาหาร
สมมุติว่านายพรานสามารถขนกวางกลับได้เพียงตัวเดียว
หากเข้าไปถึงเขาเจอกวางตัวหนึ่งแล้วก็จะล่าแล้วขนมา
แต่ต่อมาถ้าเจอกวางตัวใหม่ซึ่งใหญ่กว่า ก็จะตัดสินใจทิ้งตัวเก่าไป
พอเดินไปต่อก็อาจเจอกวางอีกตัว ถ้าเจอตัวใหญ่กว่าก็ล่าแล้วขนมาอีก
แต่ถ้าตัวเล็กก็ปล่อยไป เก็บตัวเดิมไว้ หลังจากนั้นก็เดินไปล่ากวางต่อเรื่อยๆ
ทำแบบเดิมคือเจอตัวใหญ่ก็ล่าแล้วเปลี่ยนเอามาแทน
จนสุดท้ายนายพรานก็จะได้กวางตัวใหญ่ที่สุดกลับบ้าน
การหาค่าสูงสุดของแถวลำดับก็ใช้หลักการในลักษณะเดียวกันนี้
ลองสร้างแถวลำดับของน้ำหนักของกวางที่นายพรานเจอในป่า แล้วใช้ while
เพื่อไล่หาค่าน้ำหนักของตัวที่มากที่สุดดู อาจเขียนได้ดังนี้
var kwang = [53.2, 41.5, 63.4, 77.2, 49.9, 66.8, 58.3]; // น้ำหนักกวาง ๗ ตัว
var naksut = 0; // นำหน้กตัวที่หนักที่สุด
var i_nak; // ลำดับตัวที่หนักที่สุด
var i = 0;
var len = kwang.length;
while (i < len) {
if (kwang[i] > naksut) {
naksut = kwang[i];
i_nak = i;
}
i++;
}
alert(
"ตัวที่หนักสุดคือตัวที่ " + (i_nak + 1) + " หนัก " + kwang[i_nak] + " กก."
); // ได้ ตัวที่หนักสุดคือตัวที่ 4 หนัก 77.2 กก.
การเรียงลำดับข้อมูลในแถวลำดับใหม่
วิธีการจัดเรียงสมาชิกในลิสต์ตามลำดับค่ามากน้อยนั้นมีอยู่หลายวิธี
แต่วิธีที่เข้าใจง่ายที่สุดและนิยมสอนกันในเบื้องต้นก็คือ
การเรียงลำดับแบบฟอง (bubble sort)
คือตรวจดูค่าแล้วสลับลำดับทีละคู่ไปเรื่อยๆ โดยไล่จากตัวแรกกับตัวที่สอง
ไปตัวที่สองกับตัวที่สาม แล้วไล่ไปเรื่อยๆจนถึงตัวรองสุดท้ายกับตัวสุดท้าย
จากนั้นก็วนสลับอย่างนี้ไปอีกเรื่อยๆจนเรียงกันหมด
การเรียงค่าจากน้อยไปมากโดยใช้การเรียงลำดับแบบฟองอาจเขียนโค้ดได้ดังนี้
var ar = [2, 27, 6, 12, 15, 1]; // แถวลำดับที่ต้องการเอามาเรียง
var s = "";
var len = ar.length;
var i = 1;
while (i < len) {
var j = 0;
while (j < len - i) {
if (ar[j] > ar[j + 1]) { // ถ้าตัวซ้ายมากกว่าตัวขวาให้สลับ
var aa = ar[j + 1];
ar[j + 1] = ar[j];
ar[j] = aa;
}
j++;
}
i++;
s += ar + "\n";
}
alert(s);
ได้
2,6,12,15,1,27
2,6,12,1,15,27
2,6,1,12,15,27
2,1,6,12,15,27
1,2,6,12,15,27
จะเห็นว่าในแต่ละรอบที่วนซ้ำมีการเปลี่ยนการจัดเรียงไปเรื่อยๆ
ในที่สุดค่าทั้งหมดก็เรียงกันจากน้อยไปมาก
หากต้องการเปลี่ยนเงื่อนไขในการเรียง ที่จริงแล้วก็อาจทำได้โดยแค่แทนที่ตรง
ar[j] > ar[j + 1]
ด้วยอย่างอื่น
เช่นหากเปลี่ยนเครื่องหมายมากกว่าเป็นน้อยกว่า
จะกลายเป็นการเรียงค่าจากมากไปน้อยแทน
เราอาจเขียนวิธีนี้ใหม่เป็นฟังก์ชันในรูปทั่วไปได้ว่า
var riang = function(arr, func) {
var len = arr.length;
var i = 1;
while (i < len) {
var j = 0;
while (j < len - i) {
if (func(arr[j], arr[j + 1]) > 0) {
var aa = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = aa;
}
j++;
}
i++;
}
};
var ar = [2, 27, 6, 12, 15, 1];
f = function(a, b) {
return a - b;
};
riang(ar, f);
alert(ar); // ได้ 1,2,6,12,15,27
ในที่นี้ func แทนฟังก์ชันสำหรับใช้ในการจัดเรียง
ฟังก์ชันนี้จะต้องรับตัวแปรเข้ามา ๒ ตัว ในที่นี้คือ a และ b
โดยฟังก์ชันนี้จะเอา a และ b
มาเข้าตัวดำเนินการหรือทำอะไรบางอย่างเพื่อคืนค่าออกมา หากค่า มากกว่า 0
จะเกิดการสลับค่าตัวเลข
ดังนั้นเมื่อให้ฟังก์ชันคืนค่า a-b แบบนี้
ผลก็เลยเท่ากับเป็นการสั่งให้เรียงจากน้อยมามาก
ในทางตรงข้าม หากต้องการเรียงจากมากไปน้อยก็แค่เขียนแก้ฟังก์ชันใหม่โดยสลับ a กับ
b แบบนี้
f = function(a, b) {
return b - a;
};
riang(ar, f);
alert(ar); // ได้ 27,15,12,6,2,1
กรณีที่สมาชิกเป็นสายอักขระนั้นอาจเขียนฟังก์ชันการเรียงได้ดังนี้
f = function(a, b) {
return a > b;
};
var ar = ["d", "c", "e", "a", "b"];
riang(ar, f);
alert(ar); // ได้ a,b,c,d,e
การเรียงโดยใช้เมธอด sort
ในจาวาสคริปต์ข้อมูลชนิดแถวลำดับจะมีเมธอด .sort ติดตัว
สามารถใช้เพื่อเรียงค่าได้อย่างง่ายดาย
การใช้ .sort นั้นหากไม่ได้กำหนดฟังก์ชันในการเรียงไว้
โดยปกติค่าจะเรียงจากน้อยไปมาก
เมธอดนี้ทั้งจัดเรียงแถวลำดับที่ใส่เข้าไปใหม่
แล้วก็ยังคืนค่าแถวลำดับใหม่มาด้วยในขณะเดียวกัน
var ar = ["d", "c", "e", "a", "b"];
alert(ar.sort()); // ได้ a,b,c,d,e
alert(ar); // ได้ a,b,c,d,e
เพียงแต่กรณีที่ข้อมูลเป็นตัวเลขจะพบว่าผลที่ได้นั้นออกมาไม่เป็นไปตามที่หวัง
เพราะเวลาใช้ .sort นั้น
ข้อมูลทั้งหมดในนั้นจะถูกตีความเป็นตัวอักษรก่อนจะถูกนำมาเปรียบเทียบ
เช่น
var ar = [5, 1, 3, 19, 11, 2];
ar.sort();
alert(ar); // ได้ 1, 11, 19, 2, 3, 5
จะเห็นว่าการเรียงนั้นไม่ได้เป็นไปตามลำดับตัวเลข แต่เป็นการเรียงตามตัวอักษร
จึงทำให้ 11 และ 19 มาก่อน 2
ตรงนี้สามารถแก้ด้วยการใส่ฟังก์ชันที่กำหนดรูปแบบการเรียงลงไป
หากต้องการกำหนดรูปแบบการจัดเรียงตามที่ตัวเองต้องการสามารถทำได้โดยใส่ฟังก์ชันการจัดเรียงเข้าไปในเมธอด
.sort
หลักการเหมือนกับฟังก์ชันที่ใช้ในตัวอย่างที่แล้ว
แต่จะต่างกันตรงที่ค่าถูกป้อนเข้าไปนั้นจะเป็นข้อมูลที่ถูกผ่านการเปลี่ยนเป็นสายอักขระไปแล้ว
เช่น หากต้องการให้สายอักขระเรียงจากมากไปน้อยอาจเขียนฟังก์ชันแบบนี้
f = function(a, b) {
return a < b;
};
var ar = ["d", "c", "e", "a", "b"];
ar.sort(f);
alert(ar); // ได้ e,d,c,b,a
เพียงแต่หากข้อมูลที่ใส่เข้าไปเป็นตัวเลขอยู่แล้ว
เมื่อเจอเครื่องหมายลบก็จะถูกเปลี่ยนกลับเป็นตัวเลขอีก
ดังนั้นจะสามารถใช้เครื่องหมายลบได้ง่ายๆแบบนี้
var f = function(a, b) {
return b - a;
};
var ar = [5, 1, 3, 19, 11, 2];
ar.sort(f)
alert(ar); // ได้ 19,11,5,3,2,1
การกลับลำดับข้อมูลจากหลังมาหน้า
ถ้าต้องการกลับลำดับจากเดิมจากหลังมาหน้าอาจทำได้โดยสร้างแถวลำดับใหม่มาแล้วไล่เอาข้อมูลจากแถวลำดับเดิม
var kazoe = ["อิจิ", "นิ", "ซัง", "ชิ"];
var kazoe0 = [];
var i = kazoe.length - 1;
while (i >= 0) {
kazoe0.push(kazoe[i]);
i--;
}
alert(kazoe0); // ได้ ชิ,ซัง,นิ,อิจิ
นอกจากนี้ แถวลำดับมีเมธอด reverse ซึ่งใช้เพื่อทำการกลับลำดับได้อย่างง่าย
เมธอดนี้ทั้งกลับลำดับให้แถวลำดับที่ใส่เข้าไป
แล้วก็ยังคืนค่าที่ได้มาด้วยในเวลาเดียวกัน
var kazoe = ["อิจิ", "นิ", "ซัง", "ชิ"];
alert(kazoe.reverse()); // ได้ ชิ,ซัง,นิ,อิจิ
alert(kazoe); // ได้ ชิ,ซัง,นิ,อิจิ
สรุปเมธอดทั้งหมดที่ใช้ได้ในข้อมูลแถวลำดับ
ต่อไปเป็นตารางแสดงเมธอดทั้งหมดที่มีติดตัวอยู่ในข้อมูลแถวลำดับ
เพียงแต่ว่าที่แนะนำในนี้คือเฉพาะที่ใช้ใน ES3 ได้เท่านั้น ส่วนใน ES5 และ ES6
มีเมธอดเพิ่มมาอีกมาก ซึ่งจะเขียนถึงต่อไปในส่วนเนื้อหาของ ES5 และ ES6
ชนิด |
เมธอด |
ความหมาย |
ตัวอย่าง |
แค่คืนค่าใหม่ |
slice |
หยิบเอาบางส่วนในแถวลำดับ |
ar.slice(1,4) |
concat |
เชื่อมแถวลำดับเข้าด้วยกัน |
ar1.concat(ar2) |
join |
เชื่อมสมาชิกในแถวลำดับเข้าด้วยกันเป็นสายอักขระ |
ar.join(" ") |
แก้แถวลำดับเดิม |
push |
ใส่ข้อมูลเพิ่มต่อท้ายให้แถวลำดับ |
ar.push(x) |
unshift |
ใส่ข้อมูลเพิ่มต่อด้านหน้าแถวลำดับ |
ar.unshift(x) |
pop |
เอาข้อมูลตัวท้ายสุดออกจาแถวลำไดับ |
ar.pop() |
shift |
เอาข้อมูลตัวแรกออกจากแถวลำดับ |
ar.shift() |
splice |
เอาข้อมูลในลำดับที่ระบุออกจากแถวลำดับ แล้วแทรกข้อมูลใหม่ลงไป |
ar.splice(1,1) |
sort |
เรียงข้อมูลในแถวลำดับตามค่า |
ar.sort(f) |
reverse |
กลับลำดับข้อมูลในแถวลำดับจากหลังมาหน้า |
ar.reverse() |