我的任务是编写代码以使用IComparable
和我们的自定义类型(Product)。
Product类型具有名为OrdinalNumber
的属性,该属性是排序操作的比较属性。序数的一个例子可以是这样的:1 2 3 3 5 6 7 7 9等。例程必须替换重复或缺失的序数并对结果进行排序。
我找到了这个例子,让它运转起来。 https://msdn.microsoft.com/en-us/library/w56d4y5z(v=vs.110).aspx
有人可以帮帮我吗?
我不想对DataTable进行排序。我们目前有代码对DataTable进行排序,我们希望重写该代码以使用名为Product的自定义类型。我粘贴的示例代码使用新的Product类。
这是我到目前为止所做的:
Imports System.Collections.Generic
Public Class Product
Implements IEquatable(Of Product)
Implements IComparable(Of Product)
Public Property ProductName() As String
Get
Return m_ProductName
End Get
Set(value As String)
m_ProductName = value
End Set
End Property
Private m_ProductName As String
Public Property ProductId() As Integer
Get
Return m_ProductId
End Get
Set(value As Integer)
m_ProductId = value
End Set
End Property
Private m_ProductId As Integer
Public Property OrdinalNumber() As Integer
Get
Return m_OrdinalNumber
End Get
Set(value As Integer)
m_OrdinalNumber = value
End Set
End Property
Private m_OrdinalNumber As Integer
Public Overrides Function ToString() As String
Return "Ordinal Number: " & OrdinalNumber & " ID: " & ProductId & " Name: " & ProductName
End Function
Public Overrides Function Equals(obj As Object) As Boolean
If obj Is Nothing Then
Return False
End If
Dim objAsProduct As Product = TryCast(obj, Product)
If objAsProduct Is Nothing Then
Return False
Else
Return Equals(objAsProduct)
End If
End Function
Public Function SortByNameAscending(name1 As String, name2 As String) As Integer
Return name1.CompareTo(name2)
End Function
Public Function CompareTo(compareProduct As Product) As Integer _
Implements IComparable(Of Product).CompareTo
If compareProduct Is Nothing Then
Return 1
Else
Return Me.OrdinalNumber.CompareTo(compareProduct.OrdinalNumber)
End If
End Function
Public Overrides Function GetHashCode() As Integer
Return OrdinalNumber
End Function
Public Overloads Function Equals(other As Product) As Boolean Implements IEquatable(Of Product).Equals
If other Is Nothing Then
Return False
End If
Return (Me.OrdinalNumber.Equals(other.OrdinalNumber))
End Function
End Class
答案 0 :(得分:2)
我不确定为什么会对SelectionSort
的Bingo变体(现在通过编辑进行编辑)有这样的关注。当有许多重复值时,宾果游戏版本的SelectionSort版本稍微快一点,但只是略有不同。它不是一种专门针对存在欺骗行为的情况的分拣机。它们都很慢。
How would I implement a selection or "bingo" sort using List.Sort
那不是它的工作原理。实际的排序机制内置于.NET Framework中。在List.Sort()
的情况下,它将根据需要选择3种中的一种。您可以提供比较机制。
给定{1,3,5,5,7,9,15}
的数据集1
和3
的元素总是低于5
或1024
,因此缺少的元素不是问题。您希望如何比较重复值。
有几种选择:
Dim sortedProds = myProducts.OrderBy(Function (j) j.Ordinal).ToList()
时间: ~6 ms 适用于20k项目
如果你想对dupes做一些事情,比如用Id:
Dim ProdsL = myProducts.OrderBy(Function(j) j.Ordinal).
ThenBy(Function(k) k.Id).ToList()
时间: ~8 ms 适用于20k物品
使类实现IComparable
:
Public Function CompareTo(other As ProductItem) As Integer _
Implements IComparable(Of ProductItem).CompareTo
If Ordinal < other.Ordinal Then Return -1
If Ordinal > other.Ordinal Then Return 1
' equal, return the lower ID or:
'Return 0
If Id < other.Id Then Return -1
Return 1
End Function
用法:
myProducts.Sort(Function(x, y) x.CompareTo(y))
时间: ~28 ms ,适用于20k物品
您还可以使用执行比较的方法,这意味着您不必实施IComparable
,除非它在其他情况下具有价值。
Private Function ProductComparer(x As ProductItem, y As ProductItem) As Integer
If x.Ordinal < y.Ordinal Then Return -1
If x.Ordinal > y.Ordinal Then Return 1
' equal, return the lower ID or:
'Return 0
If x.Id < y.Id Then Return -1
Return 1
End Function
用法:
myProducts.Sort(AddressOf ProductComparer)
时间: 11 ms
SelectionSort
(~3650 ms)和Bingo
变化(~3590 ms)远远落后于其他变量,它们似乎不值得考虑。包含Bingo只是为了满足原始问题(即使其他地方已经有一个问题)。
Private Sub BingoSort(items As List(Of ProductItem))
' converted from https://en.wikipedia.org/wiki/Selection_sort#Variants
' for http://stackoverflow.com/q/42303395/1070452
Dim max As Int32 = items.Count - 1
Dim nextVal = items(max).Ordinal
Dim value As Int32
Dim tmp As ProductItem
For i As Int32 = max - 1 To 0 Step -1
If items(i).Ordinal > nextVal Then
nextVal = items(i).Ordinal
End If
Next
While (max > 0) And (items(max).Ordinal = nextVal)
max -= 1
End While
While (max > 0)
value = nextVal
nextVal = items(max).Ordinal
For i As Int32 = max - 1 To 0 Step -1
If items(i).Ordinal = value Then
tmp = items(i)
items(i) = items(max)
items(max) = tmp
max -= 1
ElseIf items(i).Ordinal > nextVal Then
nextVal = items(i).Ordinal
End If
Next
While (max > 0) And (items(max).Ordinal = nextVal)
max -= 1
End While
End While
End Sub
用法:
BingoSort(myProducts)
时间: ~3590 ms ,适用于20k物品。
请注意,如果没有欺骗(或原始列表以Id
顺序开头),则结果与linq&#39; s OrderBy
Dim Valid = ProdsLinq.SequenceEqual(ProdsBingo)
鉴于表现不佳,似乎没有理由在这里使用它。 IComparable
可让您决定如何打破重复项,Linq和List.Sort(IComparable)
的速度更快。但
请注意,DataTable
:
myDT.DefaultView.Sort = "Ordinal ASC"
' or
myDT.DefaultView.Sort = "Ordinal ASC, Id ASC"