บทความนี้เรามาทำความเข้าใจและเขียนโปรแกรมเพื่อหาข้อมูลลำดับที่ n จากลิสต์ของข้อมูลด้วยภาษาไพธอน โดยทดสอบกับ Python และ Micropython กัน
ปัญหา
ถ้ามีข้อมูลตัวเลขอยู่ในลิสต์ และต้องการทราบว่าข้อมูลที่น้อยที่สุดลำดับที่ n คือ ค่าใด
แนวคิด
จากปัญหาที่กำหนดขึ้น เมื่อพิจารณาจะพบรายการปัญหาย่อย ๆ ได้แก่
- ข้อมูลที่เก็บนั้นถูกจัดเรียงแล้วหรือไม่ เพราะถ้าจัดเรียงแล้วนั่นหมายความว่าการหาค่ามากสุดและน้อยสุดนั้นเป็นเพียงการดูข้อมูล ณ ลำดับที่ต้องการ
- ถ้ายังไม่ได้จัดเรียง เราจะจัดเรียงข้อมูลอย่างไร และจัดเรียงแบบน้อยไปมากได้อย่างไร
- ถ้าในลิสต์มีข้อมูลที่ซ้ำกันจะทำอย่างไร
- ถ้าลำดับที่ต้องการดูนั้นอยู่นอกช่วงของลำดับที่มีอยู่จริงจะทำอย่างไร
เตรียมข้อมูล
จากทั้ง 4 ข้อจะพบว่าสิ่งแรกที่ต้องทำให้ได้ก่อนคือการเก็บข้อมูลลงในลิสต์ โดยในการทดลองนี้เลือกใช้การสุ่มค่าแทนการรับค่าเข้ามา และสุ่มค่าตัวเลขจำนวนเต็มจำนวน 20 ชุด ซึ่ง esp8266 และ esp32 ใช้โค้ดดังนี้ และตัวอย่างผลของการสุ่มเป็นดังภาพที่ 1
import random
# 1 สุ่มตัวเลข
data = []
for i in range(20):
data.append(random.getrandbits(4))
print(data
สำหรับ Raspberry Pi หรือเครื่องคอมพิวเตอร์ทั่วไปใช้การสุ่มดังโค้ดต่อไปนี้ และตัวอย่างของการสุ่มเป็นดังภาพที่ 2
import random
# 1 สุ่มตัวเลข
data = []
for i in range(20):
data.append(random.randint(0,16))
print(data)
จากโค้ดด้านบนจะพบว่าการสุ่มค่าที่ใช้เป็นคำสั่ง randint() เพื่อสุ่มค่าจาก a ไปถึง (b-1) ตามรูปแบบการใช้งานดังนี้
ค่าที่สุ่มได้ = random.randint( a, b )
จากตัวอย่างของการสุ่มค่าจะพบว่ามีการสร้างวัตถุประเภทลิสต์ชื่อ data ขึ้นมาโดยไม่ได้กำหนดค่าเริ่มต้น ซึ่งรูปแบบของการสร้างข้อมูลแบบลิสต์เป็นดังนี้
วัตถุประเภทลิสต์ = []
เมื่อมีวัตถุประเภทลิสต์หรือตัวแปรประเภทลิสต์จากการสร้างขึ้นเป็นที่เรียบร้อย การเพิ่มข้อมูลในลิสต์ทำได้ด้วยการใช้เมธอดหรือคำสั่ง append() ตามรูปแบบต่อไปนี้
วัตถุประเภทลิสต์.append( ข้อมูล )
จัดเรียงข้อมูล
การจัดเรียงข้อมูลของโครงสร้างข้อมูลลิสต์ในภาษาไพธอนใช้เมธอดหรือคำสั่ง sort() ดังรูปแบบต่อไปนี้
วัตถุแบบลิสต์.sort()
จากตัวอย่างในภาพที่ 3 จะพบว่าการ sort() เป็นการเรียงจากน้อยไปหามาก ถ้าต้องการให้เป็นการเรียงจากมากไปหาน้อยต้องทำการกลับลำดับข้อมูลในลิสต์ด้วยคำสั่ง reverse() ดังนี้
วัตถุแบบลิสต์.reverse()
ตัวอย่างโปรแกรมการเรียงข้อมูลจากการสุ่มเป็นดังนี้ และตัวอย่างผลลัพธ์เป็นดังภาพที่ 3
print("Raw data ........: {}".format(data))
data.sort()
print("Sorted ..........: {}".format(data))
data.reverse()
print("Reverse sorted ..: {}".format(data))
สร้างลิสต์ใหม่
จากภาพที่ 1, 2 และ 3 จะพบว่า ข้อมูลที่ได้จากการสุ่มมีความเป็นไปได้ที่จะเกิดซ้ำกัน เมื่อเกิดซ้ำกันเช่นในภาพที่ 3 ถ้าต้องการทราบข้อมูลน้อยที่สุดเป็นลำดับแรกจะได้ว่ามี 2 ค่า คือ 0 ในลำดับที่ 0 และ 1 ดังนั้น เมื่อหาคำตอบด้วยคำสั่งต่อไปนี้จะได้คำตอบที่ถูกต้อง
print(“1st = {}”.format(data[0]))
แต่ถ้าดูลำดับที่ 2 ด้วยคำสั่งต่อไปนี้จะได้ว่าคำตอบยังคงเป็น 0 ซึ่งเป็นค่าที่น้อยที่สุดเป็นอันดับแรก
print(“2nd = {}”.format(data[1]))
ดังนั้น เราจะสร้างลิสต์ใหม่ที่ไม่มีข้อมูลซ้ำกันด้วยการกระทำดังนี้
print("Raw data ........: {}".format(data))
data.sort()
print("Sorted ..........: {}".format(data))
newData = []
for i in range(len(data)):
if data[i] not in newData:
newData.append( data[i] )
print("New list ........: {}".format(newData))
ด้วยเหตุนี้จะได้ว่าลิสต์ใหม่ที่สร้างขึ้นอาจจะมีขนาดเท่าเดิมหรือน้อยกว่าเดิม และสมาชิกภายในลิสต์ไม่มีค่าใดซ้ำกันดังตัวอย่างในภาพที่ 4
การตรวจสอบหรือค้นหาข้อมูลในลิสต์เพื่อใช้ในการตัดสินใจในการเพิ่มข้อมูลนั้นเข้าไปในลิสต์อาศัยคำสั่ง in ซึ่งได้คำตอบเป็นจริงหรือเท็จ ดังรูปแบบต่อไปนี้
ข้อมูล in วัตถุประเภทลิสต์
ดังนั้น ถ้าต้องการตรวจสอบว่าไม่มีข้อมูลนี้ในลิสต์ใช่หรือไม่จึงเปลี่ยนรูปแบบการเขียนเป็นดังนี้
ข้อมูล not in วัตถุประเภทลิสต์
ตรวจสอบช่วงของข้อมูล
การตรวจสอบช่วงข้อมูลเพื่อป้องกันการหาลำดับที่อยู่มากกว่าหรือน้อยกว่าช่วงค่าของตัวแปรลิสต์ที่ได้จากขั้นตอนก่อนหน้านี้ต้องอาศัยความเข้าใจเกี่ยวกับคุณลักษณะของตัวแปรประเภทลิสต์ เช่น ตัวแรกจะเริ่มจากลำดับที่ 0 ลำดับสุดท้ายคือ -1 เป็นต้น
ด้วยเหตุนี้ค่าที่รับเข้ามาจะต้องไม่เกินขนาดที่มากที่สุดของตัวแปรลิสต์ซึ่งหาได้จากการนับจำนวนสมาชิกในลิสต์ด้วยคำสั่ง len() ดังรูปแบบการใช้งานต่อไปนี้
จำนวนสมาชิก = len( วัตถุประเภทลิสต์ )
ดังนั้น ช่วงค่าที่ใช้ในการหาลำดับจึงเป็น 1 ถึง (จำนวนสมาชิก+1) และค่าที่ใช้นำไปหา n คือ 0 ถึง (จำนวนสมาชิก)
ค้นหาและรายงานผล
ตัวอย่างผลลัพธ์ในภาพที่ 5 เป็นตัวอย่างผลลัพธ์จากการหาค่าที่น้อยกว่าลำดับแรก การค้นหาลำดับที่เกินกว่าช่วงที่มี และการค้นหาข้อมูลลำดับที่ 2 ดังโค้ดตัวอย่างต่อไปนี้
n = -5
if (n in range(1, len(newData)+1)):
print(newData[n-1])
else:
print("{} : Out of range!".format(n))
n = 100
if (n in range(1, len(newData)+1)):
print(newData[n-1])
else:
print("{} : Out of range!".format(n))
n = 2
if (n in range(1, len(newData)+1)):
print(newData[n-1])
else:
print("{} : Out of range!".format(n))
ตัวอย่างโปรแกรม
จากแนวคิดในการแก้ปัญหาทั้งหมดสามารถเขียนเป็นโปรแกรมสำหรับ esp8266 และ esp32 ได้ดังนี้
# เราจะหาข้อมูลลำดับที่ n จากลิสต์ได้อย่างไร?
import random
# 1 สุ่มตัวเลข
data = []
for i in range(20):
data.append(random.getrandbits(4))
# 2 เรียงข้อมูล
print("Raw data ........: {}".format(data))
data.sort()
print("Sorted ..........: {}".format(data))
# 3 สร้างลิสต์ใหม่ที่ไม่เก็บข้อมูลซ้ำกัน
newData = []
for i in range(len(data)):
if data[i] not in newData:
newData.append( data[i] )
print("New list ........: {}".format(newData))
# 4-5 find
n = int(input("data?"))
if (n in range(1, len(newData)+1)):
print(newData[n-1])
else:
print("{} : Out of range!".format(n))
สำหรับ Raspberry Pi หรือเครื่อง PC ที่เป็น Windows, macOS หรือ Linux เขียนดังนี้
# เราจะหาข้อมูลลำดับที่ n จากลิสต์ได้อย่างไร?
import random
# 1 สุ่มตัวเลข
data = []
for i in range(20):
data.append(random.randint(0,16))
# 2 เรียงข้อมูล
print("Raw data ........: {}".format(data))
data.sort()
print("Sorted ..........: {}".format(data))
# 3 สร้างลิสต์ใหม่ที่ไม่เก็บข้อมูลซ้ำกัน
newData = []
for i in range(len(data)):
if data[i] not in newData:
newData.append( data[i] )
print("New list ........: {}".format(newData))
# 4-5 find
n = int(input("data?"))
if (n in range(1, len(newData)+1)):
print(newData[n-1])
else:
print("{} : Out of range!".format(n))
จากตัวอย่างโปรแกรมจะพบว่ามีการเขียนส่วนของการรับค่า n จากผู้ใช้โดยคำสั่งรับข้อมูลคือ input() ซึ่งมีรูปแบบต่อไปนี้
ข้อมูลนำเข้า = input(ข้อความที่แสดง)
เนื่องจากในบางระบบค่าที่รับเข้าอาจจะไม่ได้เป็นตัวเลขจำนวนเต็มจึงทำการแปลงข้อมูลที่นำเข้าเป็นตัวเลขจำนวนเต็มด้วยคำสั่ง int() ดังนี้
ข้อมูลตัวเลขจำนวนเต็ม = int( ข้อมูล )
สรุป
จากบทความนี้จะพบว่า การแก้ปัญหาโจทย์ด้วยภาษาไพธอนนั้นไม่ยุ่งยากเนื่องจากเป็นภาษาที่มีไลบรารีให้ผู้ใช้เรียกใช้งานอย่างครบครัน แต่วิธีการแก้ปัญหาเป็นสิ่งที่ผู้เขียนโปรแกรมจะต้องคิดและอธิบายการเขียนโปรแกรมออกมาให้ชัดเจนเพื่อสะดวกในการแปลให้เป็นชุดคำสั่ง สุดท้ายนี้ขอให้สนุกกับการเขียนโปรแกรมครับ
แหล่งอ้างอิง
- Dalke Andrew and Hettinger Raymond. “Sorting HOW TO”
(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-07-30, 2021-11-03