[英]vb.net sort list of objects with custom order
I have a list of objects and I'm trying to sort by two properties with one property being sorted by a custom order. 我有一个对象列表,我正在尝试按两个属性排序,其中一个属性按自定义顺序排序。 The list has properties of ReqType and PartNumber.
该列表具有ReqType和PartNumber的属性。 ReqType will be "M", "B", "S", or null and I would like to sort the list in that order.
ReqType将为“ M”,“ B”,“ S”或null,我想按该顺序对列表进行排序。 Then sort by PartNumber.
然后按PartNumber排序。
Input list:
PartNumber ReqType
124 B
125 M
123 B
121 S
120 M
115
Expected Sort:
PartNumber ReqType
120 M
125 M
123 B
124 B
121 S
115
I started with the code below but that only sorts ReqType alphabetically. 我从下面的代码开始,但这仅按字母顺序对ReqType进行排序。
Return EBom.OrderBy(Function(f) f.ReqType).ThenBy(Function(f) f.PartNumber).ToList
I then found a method to create a custom sort order using the code below. 然后,我找到了一种使用下面的代码创建自定义排序顺序的方法。 Though using Ebom.Sort() doesn't seem to allow me to tack on the second sort order for PartNumber.
尽管使用Ebom.Sort()似乎不允许我对PartNumber进行第二排序。 I realize I could probably add the PartNumber sorting to the custom function but that seems like a lot of work.
我意识到我可能可以将PartNumber排序添加到自定义函数中,但这似乎需要大量工作。
EBom.Sort()
Return EBom.ToList
Implements IComparable(Of EBomList)
Public Function SortReq(other As EBomList) As Integer Implements IComparable(Of EBomList).CompareTo
If (Me.ReqType = other.ReqType) Then
Return 0
ElseIf (Me.ReqType = "M") Then
Return -1
ElseIf (Me.ReqType = "B") Then
If (other.ReqType = "M") Then
Return 1
Else
Return -1
End If
ElseIf (Me.ReqType = "S") Then
If (other.ReqType = "M" Or other.ReqType = "B") Then
Return 1
Else
Return -1
End If
Else
Return 1
End If
End Function
Is there an easier way to sort by a custom order or at least combine the custom sort function with a .thenby(.....) to get the order I'd like? 是否有一种更简单的方法来按自定义顺序排序,或者至少将自定义排序功能与.thenby(.....)组合以获得我想要的顺序?
Cleaner code version to do this is to use a Function in the sort method like the following. 这样做的更干净的代码版本是在类似于下面的sort方法中使用Function。
d.Sort(Function(X As EBomList, Y As EBomList)
Dim Tx As Integer = InStr("MBS ", X.ReqType.PadLeft(1, " "c))
Dim Ty As Integer = InStr("MBS ", Y.ReqType.PadLeft(1, " "c))
Select Case Tx
Case Is < Ty : Return -1
Case Is > Ty : Return 1
Case Else : Return X.PartNumber.CompareTo(Y.PartNumber)
End Select
End Function)
Note it only needs to check the partnumber when the type code is the same. 注意,仅在类型代码相同时才需要检查零件号。
I am assuming your Partnumber is in fact a number. 我假设您的部件号实际上是一个数字。 If it is a string you will need to pad it as appropriate.
如果是字符串,则需要适当地填充它。 For example.
例如。
Return X.PartNumber.PadLeft(6," "c).CompareTo(Y.PartNumber.PadLeft(6," "c))
ALTERNATIVE AND FASTER APPROACH 替代和更快的方法
If you have A LOT of data you may want to consider augmenting the EBomLit to create a sort key rather than doing that string search though... 如果您有大量数据,则可能需要考虑扩大EBomLit来创建排序键,而不是进行字符串搜索...
As in... 如...
Private _ReqType As String
Private _TypeKey As Integer
Public Property ReqType As String
Get
Return _ReqType
End Get
Set(value As String)
_ReqType = value
_TypeKey = InStr("MBS ", value.PadLeft(1, " "c))
End Set
End Property
Public ReadOnly Property TypeKey As Integer
Get
Return _TypeKey
End Get
End Property
Then the sort becomes... 然后排序变成...
d.Sort(Function(X As EBomList, Y As EBomList)
Select Case X.TypeKey
Case Is < Y.TypeKey : Return -1
Case Is > Y.TypeKey : Return 1
Case Else : Return X.PartNumber.CompareTo(Y.PartNumber)
End Select
End Function)
FASTER STILL 更快的静止
You could even extend that further by creating a full sort key out of the "TypeKey" with the padded "PartNumber" and use those as a key to save the whole shebang in a SortedDictionary instead of a List. 您甚至可以通过在带有填充的“ PartNumber”的“ TypeKey”之外创建完整排序键,并将其用作键来将整个shebang保存在SortedDictionary中而不是List中,来进一步扩展该键。
Just create a list of ReqTypes and lookup the index: 只需创建一个ReqTypes列表并查找索引:
Dim sortOrder = "MBS "
Dim sortedList = List.OrderBy(Function(x) sortOrder.IndexOf(If(x.ReqType Is Nothing, " ", x.ReqType))).ThenBy(Function(x) x.PartNumber).ToList()
Note: If sorting by something other than chars then you will need to create a propper array/list of the object to compare by. 注意:如果按字符以外的其他方式进行排序,则需要创建对象的适当数组/列表以进行比较。
A bit easier with Enum
and Tuple
if those are an option: 如果可以选择使用
Enum
和Tuple
则容易一些:
Enum PartNumber As Byte : M : B : S : __ : End Enum
Dim list = New List(Of Tuple(Of PartNumber, Integer)) From {
Tuple.Create(PartNumber.B, 124),
Tuple.Create(PartNumber.M, 125),
Tuple.Create(PartNumber.B, 123),
Tuple.Create(PartNumber.S, 121),
Tuple.Create(PartNumber.M, 120),
Tuple.Create(PartNumber.__, 115)}
list.Sort()
For Each item In list
Debug.Print(item.Item2 & vbTab & item.Item1.ToString.Replace("_", ""))
Next
Output: 输出:
120 M
125 M
123 B
124 B
121 S
115
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.