vb.net按自定义顺序排序对象列表

时间:2017-02-16 21:42:27

标签: vb.net list sorting

我有一个对象列表,我正在尝试按两个属性排序,其中一个属性按自定义顺序排序。该列表具有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(.....)相结合以获取我想要的订单?

3 个答案:

答案 0 :(得分:1)

执行此操作的清洁代码版本是在sort方法中使用函数,如下所示。

    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)

请注意,只有在类型代码相同时才需要检查partnumber。

我假设您的Partnumber实际上是一个数字。如果是字符串,则需要根据需要填充它。例如。

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中。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

如果可以选择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