φυβλαςのβλογ
บล็อกของ phyblas



javascript เบื้องต้น บทที่ ๑๒: การจัดการกับข้อมูลชนิดแถวลำดับ
เขียนเมื่อ 2019/07/31 23:21
แก้ไขล่าสุด 2021/09/28 16:42


ในบทที่แล้วได้แนะนำให้รู้จักสิ่งที่เรียกว่าแถวลำดับ (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()




-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> javascript

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

ไทย

日本語

中文