Reputation: 31
I'm new to LINQ, would like to sort by a custom literal order... not sure of the syntax to do so (assuming it is possible). Thanks!
Class Foo
Sub New(Name As String, Position As Integer)
Me.Name = Name
Me.Position = Position
End Sub
Public Name As String
Public Position As Integer
End Class
Sub Main()
Dim l As New List(Of Foo)
l.Add(New Foo("Something1", 1))
l.Add(New Foo("Something2", 2))
l.Add(New Foo("Something3", 3))
Dim literalSort = ..... 'sort l by this literal order... "2, 3, 1"
Upvotes: 2
Views: 1854
Reputation: 152566
Adapting this answer to VB:
Dim order = New Integer() {2,3,1}
Dim literalSort = l.OrderBy(Function(i) If(order.Contains(i), 0, 1)) _
.ThenBy(Function(i) Array.IndexOf(order, i)) _
.ThenBy(Function(i) i) ' sort rest numerically
Upvotes: 1
Reputation: 27342
It sounds like what you need is a customer comparer that implements IComparer(Of Foo)
.
The example that follows sorts the items in the list according to the Value
which is what I have assumed you are after. It should be easier enough to change this if it is not exactly as you want.
Public Class SpecificListComparer
Implements IComparer(Of Foo)
Private _order As Integer() = {2, 3, 1}
Public Function Compare(x As Foo, y As Foo) As Integer Implements IComparer(Of Foo).Compare
'TODO - check for null values
If x.Value = y.Value AndAlso x.Name = y.Name Then Return 0
If x.Value = y.Value Then Return x.Name.CompareTo(y.Name)
Return Array.IndexOf(_order, x.Value).CompareTo(Array.IndexOf(_order, y.Value))
End Function
End Class
Then you just use it like this:
l.Sort(New SpecificListComparer)
Upvotes: 0
Reputation: 1583
Given the seeming arbitrary nature of the ordering you want to achieve, I'd create a method with a case statement and then return the order you want, based on the position:
Public Function OrderFoo (ByVal foo as Foo) as Integer
Select Case foo.Position
Case 2
Return 1
Case 3
Return 2
Case 1
Return 3
Case Else
Return 100
End Select
End Function
Call the method in the OrderBy
in LINQ and make sure you document why you're choosing the ordering that you are.
You should be able to call the method like below:
From foo In l _
Select foo _
Order By OrderFoo(foo)
Upvotes: 1
Reputation: 27342
This will create a new list ordered as specified in the orderedNumbers array:
Dim l As New List(Of Foo)
l.Add(New Foo("Something1", 1))
l.Add(New Foo("Something2", 2))
l.Add(New Foo("Something3", 3))
Dim orderedNumbers As Integer() = {2, 3, 1}
Dim outputList As New List(Of Foo)
For Each num In orderedNumbers
outputList.Add(l.Item(num - 1))
Next
Upvotes: 0