Jump to content

Sorting a string numerically and alphabetically


Go to solution Solved by Andreik,

Recommended Posts

I have a string that is used to load a combo or listview. As its a string sorting, the combo does not work correctly, neither does _ArraySort so I have created a function. The function works but it seems like a lof of faff for what it does. I think there must be a better\quicker way. Is there?  It uses Melba's UDF here

#include <Array.au3>
#include 'ArrayMultiColSort.au3'

ConsoleWrite('String: ' & _SortString("2|3|4|4 Part|7|8|9|12|13|15|21|28|31|35|OB1|NORTH|SOUTH|BORDER|3 Part|4 Past") & @crlf)

Func _SortString($s_Sort, $b_AsArray = False)
    Local $s_AlphaCount = 0
    Local $s_NumCount = 0

    ; Step 1: Split the string into an array
    Local $as_Split = StringSplit($s_Sort, '|')

    ; loop to get the count of alpha string and mixed string
    For $i = 1 To $as_Split[0]
        If StringIsDigit(StringLeft($as_Split[$i], 1)) Then
            $s_NumCount += 1
        Else
            $s_AlphaCount += 1
        EndIf
    Next

    ; create two temp arrays
    Local $av_Numerical[$s_NumCount + 1][2] = [[$s_NumCount, '']]
    Local $as_Alpha[$s_AlphaCount + 1] = [$s_AlphaCount]

    ; reset the counts to use as array elements
    $s_NumCount = 1
    $s_AlphaCount = 1

    For $i = 1 To $as_Split[0]
        ; Check if the first character is a digit
        If StringIsDigit(StringLeft($as_Split[$i], 1)) Then ; check if the first char is a digit
            If StringIsDigit($as_Split[$i]) Then ; check if the full string is a digit
                $av_Numerical[$s_NumCount][0] = Number($as_Split[$i])
                $s_NumCount += 1
            Else ; alpha numeric
                Local $split = StringRegExp($as_Split[$i], "(\d+)\s*(\D+)", 3)
                $av_Numerical[$s_NumCount][0] = Number($split[0])
                $av_Numerical[$s_NumCount][1] = $split[1]
                $s_NumCount += 1
            EndIf
        Else ; alpha
            ; If the first character is not a digit, assume the string is purely alphabetic and store it in the second column
            $as_Alpha[$s_AlphaCount] = $as_Split[$i]
            $s_AlphaCount += 1
        EndIf
    Next

    _ArraySort($as_Alpha, 0, 1)

    Local $aSortData[][] = [[0, 0], [1, 0]]
    _ArrayMultiColSort($av_Numerical, $aSortData, 1)

    Local $s_Ret = ''

    ; loop thorugh the array
    For $i = 1 To $av_Numerical[0][0]
        If $av_Numerical[$i][1] <> '' Then
            $s_Ret &= '|' & $av_Numerical[$i][0] & ' ' & $av_Numerical[$i][1]
        Else
            $s_Ret &= '|' & $av_Numerical[$i][0]
        EndIf
    Next

    $s_Ret &= '|' & _ArrayToString($as_Alpha, '|', 1)

    If $b_AsArray = True then Return StringSplit(StringTrimLeft($s_Ret, 1), '|')
    Return $s_Ret
EndFunc   ;==>_SortString

 

Link to comment
Share on other sites

  • Solution
Posted (edited)

Something like this?

#include <Array.au3>

Local $aData = StringSplit('2|3|4|4 Part|7|8|9|12|13|15|21|28|31|35|OB1|NORTH|SOUTH|BORDER|3 Part|4 Past', '|', 2)
NaturalCompare($aData)
_ArrayDisplay($aData)

Func NaturalCompare(ByRef $aData)
    Local $vTemp, $i, $j
    Local $hDll = DllOpen('Shlwapi.dll')
    For $i = 1 To UBound($aData) - 1
        $j = $i
        While $j > 0 And DllCall($hDll, "int", "StrCmpLogicalW", "wstr", $aData[$j-1], "wstr", $aData[$j])[0] <> -1
            $vTemp = $aData[$j]
            $aData[$j] = $aData[$j-1]
            $aData[$j-1] = $vTemp
            $j -= 1
        WEnd
    Next
    DllClose($hDll)
EndFunc

 

Edited by Andreik

When the words fail... music speaks.

Link to comment
Share on other sites

Posted (edited)

Thank you @Andreik 👌 , for that function.

I extented the $aData Array a litte bit by some 04, 004, etc. entries and I share the result (as screenshot), or better the comparison of _ArraySort and NaturalCompare for the community here. Just to give a better understanding what's the effect/difference 😇 .

Local $aData = StringSplit('2|3|4|4 Part|7|8|9|12|13|004 Part|15|0004|04|4|004|21|28|31|35|OB1|NORTH|SOUTH|BORDER|3 Part|4 Past', '|', 2)

Best regards
Sven

image.png.c1a18ce2f33d719d9250af2402ef8b87.png

Edited by SOLVE-SMART

Stay innovative!

Spoiler

🌍 Au3Forums

🎲 AutoIt (en) Cheat Sheet

📊 AutoIt limits/defaults

💎 Code Katas: [...] (comming soon)

🎭 Collection of GitHub users with AutoIt projects

🐞 False-Positives

🔮 Me on GitHub

💬 Opinion about new forum sub category

📑 UDF wiki list

✂ VSCode-AutoItSnippets

📑 WebDriver FAQs

👨‍🏫 WebDriver Tutorial (coming soon)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...