2017-02-16 6 views
1

Ich habe eine Liste von Objekten und ich versuche, nach zwei Eigenschaften mit einer Eigenschaft sortiert nach einer benutzerdefinierten Reihenfolge zu sortieren. Die Liste enthält Eigenschaften von ReqType und PartNumber. ReqType wird "M", "B", "S" oder null sein und ich möchte die Liste in dieser Reihenfolge sortieren. Sortieren Sie dann nach PartNumber.vb.net Sortierliste von Objekten mit benutzerdefinierter Reihenfolge

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    

Ich begann mit dem Code unten, aber sortiert nur ReqType alphabetisch.

Ich habe dann eine Methode zum Erstellen einer benutzerdefinierten Sortierreihenfolge mit dem folgenden Code gefunden. Obwohl ich Ebom.Sort() benutze, scheint es mir nicht möglich zu sein, die zweite Sortierreihenfolge für PartNumber festzulegen. Ich weiß, dass ich wahrscheinlich die PartNumber-Sortierung zu der benutzerdefinierten Funktion hinzufügen könnte, aber das scheint eine Menge Arbeit zu sein.

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 

Gibt es einen einfacheren Weg durch eine benutzerdefinierte Reihenfolge zu sortieren oder zumindest die benutzerdefinierte Sortierfunktion mit einem .thenby zu kombinieren (.....), den Auftrag zu bekommen Ich mag würde?

Antwort

1

einfach eine Liste von ReqTypes erstellen und die Indexsuche:

Dim sortOrder = "MBS " 

Dim sortedList = List.OrderBy(Function(x) sortOrder.IndexOf(If(x.ReqType Is Nothing, " ", x.ReqType))).ThenBy(Function(x) x.PartNumber).ToList() 

Hinweis: Wenn Sie nach etwas anderem als chars sortieren, müssen Sie ein entsprechendes Array/eine Liste des zu vergleichenden Objekts erstellen.

1

Cleaner-Code-Version, um dies zu tun, verwenden Sie eine Funktion in der Sortiermethode wie folgt.

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) 

Beachten Sie, dass nur die Teilenummer geprüft werden muss, wenn der Typcode derselbe ist.

Ich gehe davon aus, dass Ihre Teilenummer tatsächlich eine Nummer ist. Wenn es sich um eine Zeichenfolge handelt, müssen Sie sie entsprechend auffüllen. Beispielsweise.

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

ALTERNATIVE UND SCHNELLER ANSATZ

Wenn Sie eine Menge Daten haben wollen, können Sie vermehren die EBomLit betrachten eher eine Art Schlüssel zu erstellen, als wenn die Zeichenfolge Suche zu tun ...

Wie 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 

dann die Sortierung wird ...

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) 

noch schneller

könnten Sie auch, dass erstrecken sie weiter durch einen vollständigen Sortierschlüssel aus dem „TypeKey“ mit dem gepolsterten „Part“ zu schaffen und solche, die als Schlüssel verwenden, um den ganzen Laden speichern in ein SortedDictionary anstelle einer Liste.

0

ein bisschen leichter mit Enum und Tuple wenn diejenigen sind eine Option:

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 

Ausgang:

120 M 
125 M 
123 B 
124 B 
121 S 
115