[TH] How to finds the nth data from a list?

บทความนี้เรามาทำความเข้าใจและเขียนโปรแกรมเพื่อหาข้อมูลลำดับที่ n จากลิสต์ของข้อมูลด้วยภาษาไพธอน โดยทดสอบกับ Python และ Micropython กัน

ปัญหา

ถ้ามีข้อมูลตัวเลขอยู่ในลิสต์ และต้องการทราบว่าข้อมูลที่น้อยที่สุดลำดับที่ n คือ ค่าใด

แนวคิด

จากปัญหาที่กำหนดขึ้น เมื่อพิจารณาจะพบรายการปัญหาย่อย ๆ ได้แก่

  1. ข้อมูลที่เก็บนั้นถูกจัดเรียงแล้วหรือไม่ เพราะถ้าจัดเรียงแล้วนั่นหมายความว่าการหาค่ามากสุดและน้อยสุดนั้นเป็นเพียงการดูข้อมูล ณ ลำดับที่ต้องการ
  2. ถ้ายังไม่ได้จัดเรียง เราจะจัดเรียงข้อมูลอย่างไร และจัดเรียงแบบน้อยไปมากได้อย่างไร
  3. ถ้าในลิสต์มีข้อมูลที่ซ้ำกันจะทำอย่างไร
  4. ถ้าลำดับที่ต้องการดูนั้นอยู่นอกช่วงของลำดับที่มีอยู่จริงจะทำอย่างไร

เตรียมข้อมูล

จากทั้ง 4 ข้อจะพบว่าสิ่งแรกที่ต้องทำให้ได้ก่อนคือการเก็บข้อมูลลงในลิสต์ โดยในการทดลองนี้เลือกใช้การสุ่มค่าแทนการรับค่าเข้ามา และสุ่มค่าตัวเลขจำนวนเต็มจำนวน 20 ชุด ซึ่ง esp8266 และ esp32 ใช้โค้ดดังนี้ และตัวอย่างผลของการสุ่มเป็นดังภาพที่ 1

import random
# 1 สุ่มตัวเลข
data = []
for i in range(20):
    data.append(random.getrandbits(4))
print(data
ภาพที่ 1 ตัวอย่างผลของการสุ่มค่า 3 ครั้ง

สำหรับ 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 )

ภาพที่ 2 ตัวอย่างการสุ่มด้วยโปรแกรมของ random.randint()

จากตัวอย่างของการสุ่มค่าจะพบว่ามีการสร้างวัตถุประเภทลิสต์ชื่อ 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))
ภาพที่ 3 ตัวอย่างการจัดเรียงข้อมูล

สร้างลิสต์ใหม่

จากภาพที่ 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

ภาพที่ 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))
ภาพที่ 5 ตัวอย่างของการค้นหาข้อมูลลำดับที่ -5, 100 และ 2

ตัวอย่างโปรแกรม

จากแนวคิดในการแก้ปัญหาทั้งหมดสามารถเขียนเป็นโปรแกรมสำหรับ 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( ข้อมูล )

สรุป

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

แหล่งอ้างอิง

  1. Dalke Andrew and Hettinger Raymond. “Sorting HOW TO”

(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-07-30, 2021-11-03