|
ข้อมูลใน Array ประกอบด้วย เช่น 1, 2, 3, 2, 3, 5, 4, 1, 5, 6, 3, 8, 5, 9
ให้ทำการตรวจสอบค่าที่ซ้ำ แล้วตัดออกให้เหลือเพียงค่าเดียว ส่วนค่าไม่ซ้ำกันเลยก็เก็บไว้
ดังนั้นตัวอย่างนี้จะได้คำตอบคือ 1, 2, 3, 5, 4, 6, 8, 9 (โดยยังไม่ต้องมีการจัดเรียงจากน้อยไปมาก หรือ มากไปน้อย)
โจทย์ข้อนี้แอดมินจะ นำเสนอวิธีการแก้ปัญหา 2 รูปแบบ โดยแบบแรกจะเป็นการใช้กระบวนการคิดแบบเป็นขั้นเป็นตอน หรือที่เราเรียกว่าอัลกอริทึ่ม (Algorithm) ซึ่งแอดมินใช้ VB6 มาเป็นตัวหลักในการแก้โจทย์นี้ เนื่องจาก VB6 ไม่ได้มี Class ไฮโซเลิศหรู แต่ก็ยังสามารถหาคำตอบออกมาได้เหมือนกัน โดยอาศัยแค่คำสั่งพื้นฐานง่ายๆทั่วไป แบบที่ 2 แอดมินจะใช้ความเก่ง หรือความเป็นสำเร็จรูปของตัวแปลภาษา ... แน่นอนว่า แบบที่ 2 จะหาคำตอบได้อย่างรวดเร็วกว่าแบบที่ 1 แต่นี่มันแค่โจทย์การบ้านส่งครู เพราะในโลกแห่งความเป็นจริง เราจะได้เจอกับเงื่อนไขที่สลับซับซ้อนมากไปกว่านี้ ต้องเจอกับ Array หลายมิติ เช่น การเช็คเวลาเข้าทำงานของพนักงาน ต้องตัดค่าที่ซ้ำออกไป แล้วเลือกค่าแรกออกมา ส่วนเวลาออก ต้องตัดค่าซ้ำออกไป แล้วเลือกเวลาสุดท้ายออกมาเพื่อเป็นคำตอบ ... การใช้ความเก่งของตัวแปลภาษา จะไม่สามารถตอบโจทย์ให้เราทั้งหมดได้เลย ...
นี่คือวิธีการคิดแบบแรก โดยการนำเอาคำตอบมาเก็บไว้ที่เดิม หรือ ตัวแปร Array เดิมของมัน นั่นแหละครับ เพื่อประหยัดพื้นที่หน่วยความจำ ... แอดมินพยายามยกตัวอย่าง และทำผังขั้นตอนออกมาให้ดูแบบง่ายๆ ทั้งนี้หากท่านต้องการทำความเข้าใจให้ได้อย่างลึกซึ้งดื่มด่ำ ต้องทำการ Debugger จากโค้ดโปรแกรมด้วยตัวเองครับผม ...
หลักการคิด ... โดยเราใช้ตัวอย่างง่ายๆ เช่น (1, 2, 3, 1, 4)
- ใช้ Nested Loop วนรอบ 2 รอบ โดยรอบนอกวนตามจำนวนค่าอินพุทที่มี นั่นคือจาก 0 - 4 (จำนวน 5 ตัว) ... รอบในวนตามการนับค่าไม่ซ้ำ ซึ่งเรายังไม่รู้ค่าที่แน่นอน แต่ใช้ตัวแปร OutLen เริ่มต้น = 0 เพื่อเริ่มต้นการนับขึ้นทีละ 1 ซึ่งตัวแปร OutLen จะมีความสำคัญอย่างมาก ...
- รอบที่ 1 ลูปนอก ให้นำค่าจากใน Array (เริ่มจาก Index = 0) ไปฝากไว้ตัวแปร CurValue ... (วงลูปใน) โดยที่รอบแรกจะต้องให้ค่านั้นมันอยู่ที่เดิม มีเทคนิคง่ายๆคือให้วงรอบ For เป็นเท็จ นั่นคือ
---- For j = 0 To (OutLen - 1) หรือ For j = 0 To -1 (เรานับขึ้นคือ Default จะเป็น Step +1) <-- เงื่อนไขเท็จ จะไม่เกิดการกระทำในลูป For
---- เพิ่มค่าให้กับ OutLen ขึ้นไป 1 ==> OutLen = 1
- รอบที่ 2 ลูปนอก ค่า i = 1, ดึงค่า 2 จาก Array ออกมา ไปเก็บไว้ที่ CurValue = 2 ... (วงลูปใน) จะทำการวนรอบ 1 รอบ เพราะ
---- For j = 0 To (OutLen - 1) หรือ For j = 0 To (1 - 1) ==> For j = 0 To (0) <-- เงื่อนไขจริง
---- If InputNumber(0) = CurValue Then หรือ If 1 = 2 Then <-- เงื่อนไขเท็จ ... จบการลูป เก็บ 2 ไว้ที่เดิม แล้วเพิ่มค่า OutLen ขึ้นไป +1 ==> OutLen = 2
- รอบที่ 3 ลูปนอก ค่า i = 2, ดึงค่า 3 จาก Array ออกมา ไปเก็บไว้ที่ CurValue = 3 ... (วงลูปใน) จะทำการวนรอบ 2 รอบ เพราะ
---- For j = 0 To (OutLen - 1) หรือ For j = 0 To (2 - 1) ==> For j = 0 To (1) <-- เงื่อนไขจริง
---- If InputNumber(0) = CurValue Then หรือ If 1 = 3 Then <-- เงื่อนไขเท็จ ... กลับไปวนลูปในอีกครั้ง ทำให้ j = 1
---- If InputNumber(1) = CurValue Then หรือ If 2 = 3 Then <-- เงื่อนไขเท็จ ... จบการลูป เก็บ 3 ไว้ที่เดิม แล้วเพิ่มค่า OutLen ขึ้นไป +1 ==> OutLen = 3
- รอบที่ 4 ลูปนอก ค่า i = 3, ดึงค่า 1 จาก Array ออกมา ไปเก็บไว้ที่ CurValue = 1 ... (วงลูปใน) จะทำการวนรอบ 3 รอบ เพราะ
---- For j = 0 To (OutLen - 1) หรือ For j = 0 To (3 - 1) ==> For j = 0 To (2) <-- เงื่อนไขจริง
---- If InputNumber(0) = CurValue Then หรือ If 1 = 1 Then <-- เงื่อนไขจริง คือมีการซ้ำ
-------- กำหนดให้ blnExist = True เพื่อไม่ให้เกิดการบวก OutLen ขึ้น 1 ตอนนี้ OutLen = 3 ตามเดิม
-------- จบการวนรอบลูปในด้วย Exit For ซึ่งภาษาอื่นไม่มีใช้ แต่เราใช้เทคนิคการบังคับให้จบลูปได้ด้วย
การให้เงื่อนไขเป็นเท็จ j = OutLen นั่นคือ 3 = 3 พอมันจะกลับขึ้นไปวนรอบทำให้ For j = 0 To (OutLen - 1) หรือ For 3 = (3 - 1) หรือ For 3 = (2) <-- เท็จ
- รอบที่ 5 ลูปนอก ค่า i = 4, ดึงค่า 4 จาก Array ออกมา ไปเก็บไว้ที่ CurValue = 4 ... (วงลูปใน) จะทำการวนรอบ 3 รอบ เพราะ OutLen = 3
---- For j = 0 To (OutLen - 1) หรือ For j = 0 To (3 - 1) ==> For j = 0 To (2) <-- เงื่อนไขจริง
---- If InputNumber(0) = CurValue Then หรือ If 1 = 4 Then <-- เงื่อนไขเท็จ ... กลับไปวนลูปในอีกครั้ง ทำให้ j = 1
---- If InputNumber(1) = CurValue Then หรือ If 2 = 4 Then <-- เงื่อนไขเท็จ ... กลับไปวนลูปในอีกครั้ง ทำให้ j = 2
---- If InputNumber(2) = CurValue Then หรือ If 3 = 4 Then <-- เงื่อนไขเท็จ ... จบการลูปจะทำการวนรอบ 3 รอบ แต่เก็บ 4 ไว้ที่ค่าอินเด็กซ์ OutLen กำหนด คือ OutLen = 3 ซึ่งเดิมช่องนี้เก็บค่า 1 ที่ซ้ำเอาไว้ ... ก่อนจบ OutLen + 1 ทำให้ได้ค่า OutLen = 4
ดังนั้นเวลาเราเอาคำตอบออกมาจาก Array เดิม จะทำให้เหลือเพียง 4 ค่า นั่นคือ (1, 2, 3, 4) แต่อย่าลืมว่าเราเก็บค่าลง Array เริ่มต้นที่ค่าอินเด็กซ์ชี้ที่ 0 ดังนั้นเมื่อ OutLen = 4 ... OutLen - 1 = 4 - 1 = 3 หรือให้นับจากอินเด็กซ์ 0 ถึง 3 หรือ For i = 0 To 3 ... จบ
มาดูโค้ดในส่วนของ VB6 ...
- ' / --------------------------------------------------------------------------------
- ' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
- ' / eMail : thongkorn@hotmail.com
- ' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
- ' / Facebook: https://www.facebook.com/g2gnet (For Thailand)
- ' / Facebook: https://www.facebook.com/commonindy (Worldwide)
- ' / Purpose : Check for duplicate values.
- ' / Microsoft Visual Basic 6.0 (SP6)
- ' / This is open source code under @CopyLeft by Thongkorn Tubtimkrob.
- ' / You can modify and/or distribute without to inform the developer.
- ' / --------------------------------------------------------------------------------
- Option Explicit
- Sub DuplicateValueAlgorithm()
- '// ชุดข้อมูลตัวเลขอินพุท
- Dim InputNumber(7) As Integer
- InputNumber(0) = 1
- InputNumber(1) = 2
- InputNumber(2) = 3
- InputNumber(3) = 1
- InputNumber(4) = 3
- InputNumber(5) = 9
- InputNumber(6) = 4
- '// นับตามจำนวนคำตอบที่ได้
- Dim OutLen As Integer
- OutLen = 0
-
- Dim i As Integer
- Dim j As Integer
- '// ลูปตามจำนวนของอินพุท (ลบ 1 เพราะเราเริ่มนับจาก 0)
- For i = 0 To UBound(InputNumber) - 1
- '// หากมีค่าซ้ำกันให้เปลี่ยนเป็น True
- Dim blnExist As Boolean
- blnExist = False
- '// นำค่าตัวเลขอินพุทแต่ละตัวเข้ามา ฝากไว้ในตัวแปร
- Dim CurValue As Integer
- CurValue = InputNumber(i)
- '// ลูปตามจำนวน InputNumber (ลบ 1 เพราะเราเริ่มนับจาก 0)
- '/ รอบแรกจะข้ามไป เพราะว่า j = 0 และ OutLen = 0 คือการเอาค่าแรกของมันมาเปรียบเทียบกันมันก็ต้องซ้ำอยู่แล้ว
- For j = 0 To OutLen - 1
- '// เปรียบเทียบว่ามีค่าตรงกับค่าเดิมหรือไม่
- If InputNumber(j) = CurValue Then
- '// พบการซ้ำ ก็ต้องออกจากลูป
- blnExist = True
- '// ออกจากลูปเมื่อกำหนดให้ j = OutLen (เทคนิคของการบังคับออกจากลูป For โดยไม่ใช้ Exit For)
- j = OutLen '// หรือใช้ Exit For
- 'Exit For
- End If
- Next
- '// หากไม่พบการซ้ำกัน ให้ใส่ค่าที่ตรวจสอบกลับเข้าไปใน Array ของตัวแปรเดิม (แต่ตำแหน่ง OutLen จะอยู่คนละที่กันแล้ว)
- If Not blnExist Then
- '// เพิ่มตัวเลขที่พบกลับลงไปใน InputNumber
- InputNumber(OutLen) = CurValue
- '// เลื่อนตำแหน่งขึ้นไปอีก 1
- OutLen = OutLen + 1
- End If
- Next
- '// แสดงผล
- Dim s As String
- s = ""
- For i = 0 To OutLen - 1
- s = s & InputNumber(i) & vbCrLf
- Next
- MsgBox (s)
- End Sub
- Private Sub Form_Load()
- Call DuplicateValueAlgorithm
- End
- End Sub
คัดลอกไปที่คลิปบอร์ด
มาดูโค้ดของ VB .NET (2010) ...
- ' / --------------------------------------------------------------------------------
- ' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
- ' / eMail : thongkorn@hotmail.com
- ' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
- ' / Facebook: https://www.facebook.com/g2gnet (For Thailand)
- ' / Facebook: https://www.facebook.com/commonindy (Worldwide)
- ' / Purpose : Check for duplicate values with two methods.
- ' / Microsoft Visual Basic .NET (2010) SP1
- ' / This is open source code under @CopyLeft by Thongkorn Tubtimkrob.
- ' / You can modify and/or distribute without to inform the developer.
- ' / --------------------------------------------------------------------------------
- Public Class Form1
- Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
- Call DuplicateValueAlgorithm()
- Call DuplicateValueLanguage()
- End
- End Sub
- ' / --------------------------------------------------------------------------------
- ' / การใช้ทักษะพื้นฐานทางด้านโปรแกรมมิ่ง และกระบวนการคิด (Algorithm)
- ' / โดยเราจะเอาคำตอบกลับมาเก็บไว้ที่อินพุทแบบ Array ตามเดิม
- Sub DuplicateValueAlgorithm()
- '// ชุดข้อมูลตัวเลขอินพุท (เวลาทดสอบจริงไม่ต้องยาวก็ได้ เช่น {1, 2, 3, 1, 4})
- 'Dim InputNumber() As Integer = {1, 2, 3, 1, 4}
- Dim InputNumber() As Integer = {1, 2, 3, 2, 3, 5, 4, 1, 5, 6, 3, 8, 5, 9}
- '// นับตามจำนวนคำตอบที่ได้
- Dim OutLen As Integer = 0
- '// ลูปตามจำนวนของอินพุท (ลบ 1 เพราะเราเริ่มนับจาก 0)
- For i As Integer = 0 To InputNumber.Length - 1
- '// หากมีค่าซ้ำกันให้เปลี่ยนเป็น True
- Dim blnExist As Boolean = False
- '// นำค่าตัวเลขอินพุทแต่ละตัวเข้ามา ฝากไว้ในตัวแปร
- Dim CurValue As Integer = InputNumber(i)
- '// ลูปตามจำนวน InputNumber (ลบ 1 เพราะเราเริ่มนับจาก 0)
- '/ รอบแรกจะข้ามไป เพราะว่า j = 0 และ OutLen = 0 คือการเอาค่าแรกของมันมาเปรียบเทียบกันมันก็ต้องซ้ำอยู่แล้ว
- For j As Integer = 0 To OutLen - 1
- '// เปรียบเทียบว่ามีค่าตรงกับค่าเดิมหรือไม่
- If InputNumber(j) = CurValue Then
- '// พบการซ้ำ ก็ต้องออกจากลูป
- blnExist = True
- '// ออกจากลูปเมื่อกำหนดให้ j = OutLen (เทคนิคของการบังคับออกจากลูป For โดยไม่ใช้ Exit For)
- j = OutLen '// หรือใช้ Exit For
- End If
- Next
- '// หากไม่พบการซ้ำกัน ให้ใส่ค่าที่ตรวจสอบกลับเข้าไปใน Array ของตัวแปรเดิม (แต่ตำแหน่ง OutLen จะอยู่คนละที่กันแล้ว)
- If Not blnExist Then
- '// เพิ่มตัวเลขที่พบกลับลงไปใน InputNumber
- InputNumber(OutLen) = CurValue
- '// เลื่อนตำแหน่งขึ้นไปอีก 1
- OutLen += 1
- End If
- Next
- '// แสดงผล
- Dim s As String = String.Empty
- For i As Integer = 0 To OutLen - 1
- s = s & InputNumber(i) & vbCrLf
- Next
- MsgBox(s)
- End Sub
- ' / --------------------------------------------------------------------------------
- ' / การใช้ความเก่งของตัวแปลภาษา
- Sub DuplicateValueLanguage()
- '// สร้าง List และข้อมูลตัวอย่าง
- Dim InList As New List(Of Integer)(New Integer() {1, 2, 3, 2, 3, 5, 4, 1, 5, 6, 3, 8, 5, 9})
- '// กรองข้อมูลที่ซ้ำ (Distinct) แล้วเอามันกลับไปเก็บไว้ใน List
- Dim OutList As List(Of Integer) = InList.Distinct().ToList
- '// แสดงผล
- Dim s As String = String.Empty
- For Each CurValue As Integer In OutList
- s = s & CurValue & vbCrLf
- Next
- MsgBox(s)
- End Sub
- End Class
คัดลอกไปที่คลิปบอร์ด
Conclusion: หลายคนอาจจะมองว่าโค้ดสั้นๆมันมี Performance ที่สูงกว่า ลดบั๊กหรือความผิดพลาดลงไปได้เยอะ แต่เชื่อแอดมินเถอะครับ กับงานจริงๆเราไม่ได้หาคำตอบง่ายๆแบบนี้ออกมา เพราะมันจะมีเงื่อนไข ตรรกะ จุกจิกอีกเยอะแยะมากมาย สำหรับคนที่พึ่งเริ่มฝึกเขียนโปรแกรม ก็จงพยายามคิดก่อนที่จะเขียนโปรแกรม ดังวิธีการคิดในแบบแรก เราไม่จำเป็นต้องเปิดหนังสือ และไม่ต้องไปค้นหาในเน็ต แต่ใช้กระบวนการคิดแบบเป็นขั้นเป็นตอน และที่สำคัญคือ วิธีการคิดแบบนี้ไม่ขึ้นกับภาษาใดๆ ... สวัสดี
ดาวน์โหลดโค้ดต้นฉบับ VB6 และ VB .NET (2010) ได้ที่นี่ ...
|
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|