Forum Discussion
RobbSalzmann
2 years agoValued Contributor II
The sorting posted so far relies on standard lexical ordering which produces an order that can be a bit strange for a business user:
This code will help sort things in a human, alphanumeric order:
Public Class MainClass
Public Function Main(si As SessionInfo, globals As BRGlobals, api As Object, args As ExtenderArgs) As Object
Try
Dim mbrLst As New MemberList()
Dim mbrDisplayOptions As MemberDisplayOptions = New MemberDisplayOptions() _
With{ .IncludeAllProperties = True, .IncludeMemberInfoForProperties = True}
Dim lstMembers As LIst(Of MemberInfo) =
BRApi.Finance.Metadata.GetMembersUsingFilter(si, "CorpAccounts", "A#[GAAP Account Structure].Base", True, Nothing, mbrDisplayOptions)
lstMembers.Sort(New AlphaNumericMemberInfoComparer())
mbrLst.AddMemberInfosToList(lstMembers)
Return mbrLst
Catch ex As Exception
Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
End Try
End Function
End Class
Public Class AlphaNumericMemberInfoComparer
Implements IComparer(Of MemberInfo)
Public Function Compare(x As MemberInfo, y As MemberInfo) As Integer Implements IComparer(Of MemberInfo).Compare
If x.Member.Name = y.Member.Name Then Return 0
Dim xParts() As String = Regex.Split(x.Member.Name, "(\d+)")
Dim yParts() As String = Regex.Split(y.Member.Name, "(\d+)")
For i As Integer = 0 To Math.Min(xParts.Length, yParts.Length) - 1
If xParts(i) <> yParts(i) Then
Return PartCompare(xParts(i), yParts(i))
End If
Next
Return xParts.Length.CompareTo(yParts.Length)
End Function
Private Shared Function PartCompare(x As String, y As String) As Integer
Dim a, b As Integer
Dim isNumericX As Boolean = Integer.TryParse(x, a)
Dim isNumericY As Boolean = Integer.TryParse(y, b)
If isNumericX And isNumericY Then
Return a.CompareTo(b)
End If
Return String.Compare(x, y, StringComparison.OrdinalIgnoreCase)
End Function
End Class
Alternate Sorting Result:
- JackLacava12 months agoHonored Contributor
That's neat. It could be further generalized by accepting a parameterized switch (SortOrder=<human/lcg>) and another one to switch between ordering by name or description (SortBy=<name/desc>).
- RobbSalzmann12 months agoValued Contributor II
Or, if you want something quick and LINQ-y, these will work to sort lists of MemberInfo:
''VB.net Public Sub AlphaNumericSort(ByRef members as List(Of MemberInfo) Dim sortedMembers As List(Of MemberInfo) = members _ .OrderBy(Function(memberInfo) _ If(Regex.Match(memberInfo.Member.Name, "\d+").Success, _ 'Evaluation, starts with a number? Integer.Parse(Regex.Match(memberInfo.Member.Name, "\d+").Value), _ 'True Part Integer.MaxValue)) _ 'False Part, put after all that start with a number .ToList() End Sub // C#: public void AlphaNumericSort(ref List members) { List sortedMembers = members .OrderBy ( memberInfo => Regex.Match(memberInfo.Member.Name, @"\d+").Success ? //Evaluation, starts with a number? int.Parse(Regex.Match(memberInfo.Member.Name, @"\d+").Value) : //True int.MaxValue //False, put after all that start with a number ).ToList(); }
Used like this:
Public Class MainClass Public Function Main(si As SessionInfo, globals As BRGlobals, api As Object, args As ExtenderArgs) As Object Try Dim mbrLst As New MemberList() Dim mbrDisplayOptions As MemberDisplayOptions = New MemberDisplayOptions() _ With{ .IncludeAllProperties = True, .IncludeMemberInfoForProperties = True} Dim lstMembers As List(Of MemberInfo) = BRApi.Finance.Metadata.GetMembersUsingFilter(si, "CorpAccounts", "A#[GAAP Account Structure].Base", True, Nothing, mbrDisplayOptions) '' Sort the members: AlphaNumericSort(lstMembers) mbrLst.AddMemberInfosToList(lstMembers) Return mbrLst Catch ex As Exception Throw ErrorHandler.LogWrite(si, New XFException(si, ex)) End Try End Function Public Sub AlphaNumericSort(ByRef members as List(Of MemberInfo) Dim sortedMembers As List(Of MemberInfo) = members _ .OrderBy(Function(memberInfo) _ If(Regex.Match(memberInfo.Member.Name, "\d+").Success, _ 'Evaluation, starts with a number? Integer.Parse(Regex.Match(memberInfo.Member.Name, "\d+").Value), _ 'True Part Integer.MaxValue)) _ 'False Part, put after all that start with a number .ToList() End Sub End Class
Related Content
- 4 months ago
- 10 months ago