繁体   English   中英

vb.net按自定义顺序对对象进行排序

[英]vb.net sort list of objects with custom order

我有一个对象列表,我正在尝试按两个属性排序,其中一个属性按自定义顺序排序。 该列表具有ReqType和PartNumber的属性。 ReqType将为“ M”,“ B”,“ S”或null,我想按该顺序对列表进行排序。 然后按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            

我从下面的代码开始,但这仅按字母顺序对ReqType进行排序。

Return EBom.OrderBy(Function(f) f.ReqType).ThenBy(Function(f) f.PartNumber).ToList 

然后,我找到了一种使用下面的代码创建自定义排序顺序的方法。 尽管使用Ebom.Sort()似乎不允许我对PartNumber进行第二排序。 我意识到我可能可以将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

是否有一种更简单的方法来按自定义顺序排序,或者至少将自定义排序功能与.thenby(.....)组合以获得我想要的顺序?

这样做的更干净的代码版本是在类似于下面的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)

注意,仅在类型代码相同时才需要检查零件号。

我假设您的部件号实际上是一个数字。 如果是字符串,则需要适当地填充它。 例如。

Return X.PartNumber.PadLeft(6," "c).CompareTo(Y.PartNumber.PadLeft(6," "c))

替代和更快的方法

如果您有大量数据,则可能需要考虑扩大EBomLit来创建排序键,而不是进行字符串搜索...

如...

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

然后排序变成...

    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)

更快的静止

您甚至可以通过在带有填充的“ PartNumber”的“ TypeKey”之外创建完整排序键,并将其用作键来将整个shebang保存在SortedDictionary中而不是List中,来进一步扩展该键。

只需创建一个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()

注意:如果按字符以外的其他方式进行排序,则需要创建对象的适当数组/列表以进行比较。

如果可以选择使用EnumTuple则容易一些:

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

输出:

120 M
125 M
123 B
124 B
121 S
115 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM