2017-02-16 156 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