|
บทความนี้แอดมินไปเจอคำถามอยู่ใน StackOverFlow ตัวแอดมินกลับสนใจมันขึ้นมา ก็เลยลองนำมาคิดดู ... การจัดอันดับ (Ranking) ในที่นี้หมายถึงการที่เรารับชุดข้อมูลใดๆเข้ามา ซึ่งอาจจะไม่ใช่ DataBase ที่สามารถ Query และจัดเรียงข้อมูลก่อนนำมาแสดงผล แต่เป็นแหล่งข้อมูลจากที่อื่น เช่น XML หรือ JSON เพื่อทำการคำนวณหาว่าข้อมูลแต่ละชุด ที่อยู่ในแต่ละแถวนั้นอยู่อันดับที่เท่าไหร่ คำนวณได้ทั้งแบบมากไปหาน้อย หรือ น้อยไปหามาก ... โค้ดตัวอย่างแอดมินนำมาให้ได้ศึกษากัน 2 แบบ แบบแรกคือใช้ Linq ส่วนแบบที่ 2 จะใช้ Dictionary ขอให้ทุกๆท่านลองนำมาเปรียบเทียบดูกันเองล่ะกันครับ ... (หมายเหตุ: ที่ต้องเขียนคำอธิบายโค้ดเป็นภาษาอังกฤษ เพราะแอดมินนำไปโพสต์ที่เว็บต่างประเทศครับ) ...
โค้ด Linq Implement ...
- ' / --------------------------------------------------------------------------------
- ' / 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: How to make Ranking in DataGridView with out DataBase.
- ' / Microsoft Visual Basic .NET (2010)
- ' /
- ' / This is open source code under @CopyLeft by Thongkorn Tubtimkrob.
- ' / You can modify and/or distribute without to inform the developer.
- ' / --------------------------------------------------------------------------------
- Public Class frmRankingDataGrid
- Dim dt As DataTable
- Dim MaxRow As Integer = 9
- Public Sub New()
- ' This call is required by the designer.
- InitializeComponent()
- ' Add any initialization after the InitializeComponent() call.
- Call SetupDGVData()
- End Sub
- ' / --------------------------------------------------------------------------------
- Private Sub btnPopulate_Click(sender As System.Object, e As System.EventArgs) Handles btnProcess.Click
- Call InitGrid()
- Call FillData()
- End Sub
- ' / --------------------------------------------------------------------------------
- '// Initialize DataGridView @Run Time
- Private Sub SetupDGVData()
- With dgvData
- .RowHeadersVisible = False
- .AllowUserToAddRows = False
- .AllowUserToDeleteRows = False
- .AllowUserToResizeRows = False
- .MultiSelect = True
- .SelectionMode = DataGridViewSelectionMode.FullRowSelect
- .ReadOnly = True
- .Font = New Font("Tahoma", 9)
- .RowHeadersVisible = True
- ' Autosize Column
- .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
- .AutoResizeColumns()
- '// Even-Odd Color
- .AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue
- ' Adjust Header Styles
- With .ColumnHeadersDefaultCellStyle
- .BackColor = Color.Navy
- .ForeColor = Color.Black ' Color.White
- .Font = New Font("Tahoma", 9, FontStyle.Bold)
- End With
- End With
- End Sub
- Private Sub frmRankingDataGrid_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
- Me.Dispose()
- Application.Exit()
- End Sub
- Private Sub frmRankingDataGrid_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
- Call InitGrid()
- Call FillData()
- End Sub
- ' / --------------------------------------------------------------------------------
- Private Sub InitGrid()
- dt = New DataTable
- dt.Columns.Add("A", GetType(Double))
- dt.Columns.Add("B", GetType(Double))
- dt.Columns.Add("C", GetType(Double))
- dt.Columns.Add("D", GetType(Double))
- dt.Columns.Add("E", GetType(Double))
- dt.Columns.Add("Average", GetType(Double))
- dt.Columns.Add("Dummy", GetType(Double)) '<-- Visible = False
- dt.Columns.Add("Row") '<-- Visible = False
- dt.Columns.Add("Ranking", GetType(Integer))
- dgvData.DataSource = dt
- End Sub
- ' / --------------------------------------------------------------------------------
- ' / Sample Data
- Private Sub FillData()
- Randomize()
- Dim RandomClass As New Random()
- For i As Integer = 0 To MaxRow
- Dim dr As DataRow = dt.NewRow()
- '// RandomClass.NextDouble(). A double-precision floating point number that is greater than or equal to 0.0, and less than 1.0.
- dr(0) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- dr(1) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- dr(2) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- dr(3) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- dr(4) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- Dim SumCol As Double = 0
- For iCol As Integer = 0 To 4 'MaxCol
- SumCol = SumCol + dr(iCol)
- Next
- dr(5) = Format(SumCol / 5, "0.00")
- dgvData.DataSource = dt
- '//
- dt.Rows.Add(dr)
- Next
- Try
- '// Create Dictionary with double keys.
- Dim dict As New Dictionary(Of Double, Integer)
- For i As Integer = 0 To MaxRow
- '// Column index = 6 is dummy to get double value.
- '// Prevent have some duplicate key.
- '// Example:
- '// dgvData.Item(5, i).Value = 44.1 ... but
- '// CovertDoubleFloat(44.1) = 44.099998474121094
- dgvData.Item(6, i).Value = CovertDoubleFloat(dgvData.Item(5, i).Value).ToString("G15")
- dict.Add(dgvData.Item(6, i).Value, i)
- Next
- ' Get list of keys.
- Dim keys As List(Of Double) = dict.Keys.ToList
- ' Sort the keys Accesending. (A -> Z)
- keys.Sort()
- ' Descending Z -> A
- keys.Reverse()
- ' Loop over the sorted keys.
- Dim dVal As Double
- Dim Count As Integer = 0
- For Each dVal In keys
- 'MsgBox(dVal & " - " & dict.Item(dVal))
- dgvData.Item(6, Count).Value = dVal
- dgvData.Item(7, Count).Value = dict.Item(dVal)
- Count += 1
- Next
- '// Hidden column
- dgvData.Columns(6).Visible = False
- dgvData.Columns(7).Visible = False
- '// Change position for Ranking.
- For iSource As Integer = 0 To MaxRow
- For iDest As Integer = 0 To MaxRow
- If dgvData.Item(7, iSource).Value = iDest Then
- dgvData.Item(8, iDest).Value = iSource + 1
- Exit For
- End If
- Next
- Next
- Catch ex As Exception
- MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
- End Try
- End Sub
- ' / --------------------------------------------------------------------------------
- '// https://msdn.microsoft.com/en-us/library/kc01y017(v=vs.110).aspx
- Public Function CovertDoubleFloat(ByVal doubleVal As Double) As Double
- Dim singleVal As Single = 0
- ' Double to Single conversion cannot overflow.
- singleVal = System.Convert.ToSingle(doubleVal)
- ' Conversion from Single to Double cannot overflow.
- CovertDoubleFloat = System.Convert.ToDouble(singleVal)
- End Function
- Private Sub btnExit_Click(sender As System.Object, e As System.EventArgs) Handles btnExit.Click
- Me.Close()
- End Sub
- End Class
คัดลอกไปที่คลิปบอร์ด
โค้ด Dictionary Implement ...
- ' / --------------------------------------------------------------------------------
- ' / 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: How to make Ranking in DataGridView with Dictionary.
- ' / Microsoft Visual Basic .NET (2010)
- ' /
- ' / This is open source code under @CopyLeft by Thongkorn Tubtimkrob.
- ' / You can modify and/or distribute without to inform the developer.
- ' / --------------------------------------------------------------------------------
- Public Class frmRankingDictionary
- Dim dt As DataTable
- Dim MaxRow As Integer = 9
- ' / --------------------------------------------------------------------------------
- Private Sub btnPopulate_Click(sender As System.Object, e As System.EventArgs) Handles btnProcess.Click
- Call InitGrid()
- Call FillData()
- End Sub
- ' / --------------------------------------------------------------------------------
- '// Initialize DataGridView @Run Time
- Private Sub SetupDGVData()
- With dgvData
- .RowHeadersVisible = False
- .AllowUserToAddRows = False
- .AllowUserToDeleteRows = False
- .AllowUserToResizeRows = False
- .MultiSelect = True
- .SelectionMode = DataGridViewSelectionMode.FullRowSelect
- .ReadOnly = True
- .Font = New Font("Tahoma", 9)
- ' Autosize Column
- .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
- .AutoResizeColumns()
- '// Even-Odd Color
- .AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue
- ' Adjust Header Styles
- With .ColumnHeadersDefaultCellStyle
- .BackColor = Color.Navy
- .ForeColor = Color.Black ' Color.White
- .Font = New Font("Tahoma", 9, FontStyle.Bold)
- End With
- End With
- End Sub
- ' / --------------------------------------------------------------------------------
- ' / Sample Data
- Private Sub FillData()
- Randomize()
- Dim RandomClass As New Random()
- For i As Integer = 0 To MaxRow
- Dim dr As DataRow = dt.NewRow()
- dr(0) = i + 1
- '// RandomClass.Next(0, 99) Random integer value between 0 - 99.
- '// RandomClass.NextDouble(). A double-precision floating point number that is greater than or equal to 0.0, and less than 1.0.
- dr(1) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- dr(2) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- dr(3) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- dr(4) = RandomClass.Next(0, 99) + Format(RandomClass.NextDouble(), "0.0")
- Dim SumCol As Double = 0
- For iCol As Integer = 1 To 4 'MaxCol
- SumCol = SumCol + dr(iCol)
- Next
- dr(5) = Format(SumCol / 4, "0.00")
- dgvData.DataSource = dt
- '//
- dt.Rows.Add(dr)
- Next
- Try
- '// Dictionary. This collection allows fast key lookups. A generic type, it can use any types for its keys and values.
- '// Important: Dictionary can't have the duplicate key.
- '//
- '// Create Dictionary with double keys.
- Dim dict As New Dictionary(Of Double, Integer)
- '// Key and Value Pairs for Dummies.
- For i As Integer = 0 To MaxRow
- '// Column index = 6 is dummy to get double value.
- dgvData.Item(6, i).Value = dgvData.Item(5, i).Value
- '// Key, Value
- dict.Add(dgvData.Item(6, i).Value, i)
- Next
- '/ Get list of keys.
- Dim keys As List(Of Double) = dict.Keys.ToList
- '/ Sort the keys ascending. (A -> Z)
- keys.Sort()
- '/ Descending Z -> A
- keys.Reverse()
- '//
- Dim dVal As Double
- Dim Count As Integer = 0
- '/ Loop over the sorted keys.
- For Each dVal In keys
- dgvData.Item(6, Count).Value = dVal
- dgvData.Item(7, Count).Value = dict.Item(dVal)
- Count += 1
- Next
- '// Hidden column
- dgvData.Columns(6).Visible = False
- dgvData.Columns(7).Visible = False
- '// Change position for Ranking.
- For iSource As Integer = 0 To MaxRow
- For iDest As Integer = 0 To MaxRow
- If dgvData.Item(7, iSource).Value = iDest Then
- dgvData.Item(8, iDest).Value = iSource + 1
- Exit For
- End If
- Next
- Next
- Catch ex As Exception
- MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
- End Try
- End Sub
- Private Sub frmRankingDictionary_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
- Call SetupDGVData()
- Call InitGrid()
- Call FillData()
- End Sub
- Private Sub InitGrid()
- '//
- dt = New DataTable
- dt.Columns.Add("#Row", GetType(String))
- '// Define input with integer type.
- dt.Columns.Add("A", GetType(Double))
- dt.Columns.Add("B", GetType(Double))
- dt.Columns.Add("C", GetType(Double))
- dt.Columns.Add("D", GetType(Double))
- dt.Columns.Add("Average", GetType(Double))
- dt.Columns.Add("Dummies", GetType(Double)) '<-- Visible = False
- dt.Columns.Add("Row") '<-- Visible = False
- dt.Columns.Add("Ranking", GetType(Integer))
- dgvData.DataSource = dt
- End Sub
- Private Sub frmRankingDictionary_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
- Me.Dispose()
- Application.Exit()
- End Sub
- Private Sub btnExit_Click(sender As System.Object, e As System.EventArgs) Handles btnExit.Click
- Me.Close()
- End Sub
- End Class
คัดลอกไปที่คลิปบอร์ด
ดาวน์โหลดโค้ดฉบับเต็ม VB.NET (2010) ได้ที่นี่ ... |
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|