2017-02-16 159 views
1

我有一個對象列表,我試圖按兩個屬性進行排序,一個屬性按自定義順序排序。該列表具有ReqType和PartNumber的屬性。 ReqType將是「M」,「B」,「S」或null,我想按照該順序對列表進行排序。然後按PartNumber排序。vb.net使用自定義順序排序對象列表

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(.....)來得到我想要的順序組合自定義排序功能更簡單的方法?

回答

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數組/列表來進行比較。

1

執行此操作的清除代碼版本是在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) 

注意它只需要在類型代碼相同時檢查partnumber。

我假設你的Partnumber實際上是一個數字。如果它是一個字符串,您需要根據需要進行填充。例如。

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

替代性和更快APPROACH

如果你有數據的很多,你可能要考慮擴充該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) 

還要更快

你甚至可以進一步擴展,通過建立一個完整的排序關鍵字出「TypeKey」的加襯「零件號」,並使用這些作爲一鍵拯救整個事情中一個SortedDictionary而不是一個List。

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