Natural Compare String nach PureBasic convertiert. Das scheint soweit zu funktionieren. Jetzt muss man das aber in Sortieralgorithmen wie Quicksort, Bubbelsort ... einbauen. Leider hab ich das bisher nur angewendet, mich damit aber noch nicht wirklich beschäftigt.
1. Welchen Sortieralgorithmus für Listen, Arrays
a) für wenige Einträge: <10.0000
b) für viele Einträge >10.000 - 1.000.000
2. hat da jemand gute Implementierungen bereit, in die man den Naturalsort einbauen kann?
Code für NatrualCompareString
Code: Alles auswählen
; #PB_String_Equal ; 0 wenn String1 gleich String2 ist
; #PB_String_Lower ; -1 wenn String1 kleiner als String2 ist
; #PB_String_Greater ; 1 wenn String1 größer als String2 ist
; based on C Code from
; https://github.com/sourcefrog/natsort/blob/master/strnatcmp.c
Structure pChar
a.a[0]
c.c[0]
EndStructure
Macro mac_IsDigit(C)
Bool(C >= '0' And C <= '9')
EndMacro
Macro mac_LCaseChar(Char, ReturnChar)
#DeltaChar= 'a' - 'A' ; a[97]-A[65]=32
If char >='A' And char <='Z'
ReturnChar = Char + #DeltaChar ; add 32 to LCase Char
Else
ReturnChar = Char
EndIf
EndMacro
Procedure _NaturalCompare_Right(*a.pChar, *b.pChar)
; ============================================================================
; NAME: _NaturalCompare_Right
; DESC:
; DESC:
; VAR(*a.pChar) : Pointer to 1st String (interpreted as pointerChar)
; VAR(*a.pChar) : Pointer to 2nd String (interpreted as pointerChar)
; RET.i: #PB_String_Lower, #PB_String_Equal, #PB_String_Greater
; ============================================================================
Protected I, bias
; The longest run of digits wins. That aside, the greatest
; value wins, but we can't know that it will until we've scanned
; both numbers To know that they have the same magnitude, so we
; remember it in BIAS.
While *a\c[I] And *b\c
If Not mac_IsDigit(*a\c[I]) And Not mac_IsDigit(*b\c[0])
ProcedureReturn bias
ElseIf Not mac_IsDigit(*a\c[I])
ProcedureReturn #PB_String_Lower
ElseIf Not mac_IsDigit(*b\c[0])
ProcedureReturn #PB_String_Greater
ElseIf *a\c[I] < *b\c[0]
If Not bias
bias = #PB_String_Lower
EndIf
ElseIf *a\c[I] > *b\c[0]
If Not bias
bias = #PB_String_Greater
EndIf
ElseIf Not *a\c[I] And Not *b\c[0]
ProcedureReturn bias
EndIf
I + 1
Wend
ProcedureReturn #PB_String_Equal
EndProcedure
Procedure _NaturalCompare_Left(*a.pChar, *b.pChar)
; ============================================================================
; NAME: _NaturalCompare_Left
; DESC:
; DESC:
; VAR(*a.pChar) : Pointer to 1st String (interpreted as pointerChar)
; VAR(*a.pChar) : Pointer to 2nd String (interpreted as pointerChar)
; RET.i: #PB_String_Lower, #PB_String_Equal, #PB_String_Greater
; ============================================================================
Protected I
; Compare two left-aligned numbers: the first To have a
; different value wins.
While *a\c[I] And *b\c[I]
If Not mac_IsDigit(*a\c[I]) And Not mac_IsDigit(*b\c[0])
ProcedureReturn #PB_String_Equal
ElseIf Not mac_IsDigit(*a\c[I])
ProcedureReturn #PB_String_Lower
ElseIf Not mac_IsDigit(*b\c[I])
ProcedureReturn #PB_String_Greater
ElseIf *a\c[I] < *b\c[I]
ProcedureReturn #PB_String_Lower
ElseIf *a\c[I] > *b\c[I]
ProcedureReturn #PB_String_Greater
EndIf
I + 1
Wend
ProcedureReturn #PB_String_Equal
EndProcedure
Procedure NaturalCompareString(*a.pChar, *b.pChar, Mode=#PB_String_CaseSensitive )
; ============================================================================
; NAME: NaturalCompareString
; DESC:
; DESC:
; VAR(*a.pChar) : Pointer to 1st String (interpreted as pointerChar)
; VAR(*a.pChar) : Pointer to 2nd String (interpreted as pointerChar)
; RET.i: #PB_String_Lower, #PB_String_Equal, #PB_String_Greater
; ============================================================================
Protected.i aI, bI, result
Protected.c ca, cb
While *a\c[aI] And *b\c[bI]
; Skip Tabs and Spaces
While (*a\c[aI] = 32) Or (*a\c[aI] = 9)
aI + 1
Wend
; Skip Tabs And Spaces
While (*b\c[bI] = 32) Or (*b\c[bI] = 9)
bI + 1
Wend
ca = *a\c[aI]
cb = *b\c[bI]
If (Not ca) And (Not cb) ; C++ If (!ca && !cb) {
ProcedureReturn #PB_String_Equal
EndIf
; process compare digits
If mac_IsDigit(ca) And mac_IsDigit(cb)
If ca ='0' Or cb = '0' ; if (ca == '0' || cb == '0'); one of both is a '0'
result = _NaturalCompare_Left((*a+aI), (*b+bI))
If result
ProcedureReturn result
EndIf
Else
result = _NaturalCompare_Right((*a+aI), (*b+bI))
If result
ProcedureReturn result
EndIf
EndIf
EndIf
If Mode <> #PB_String_CaseSensitive
mac_LCaseChar(ca,ca)
mac_LCaseChar(cb,cb)
EndIf
If ca < cb
ProcedureReturn #PB_String_Lower
ElseIf ca > cb
ProcedureReturn #PB_String_Greater
EndIf
aI + 1
bI + 1
Wend
ProcedureReturn #PB_String_Equal
EndProcedure
Define.s str1, str2
str1 = "foo100bar99baz0.txt"
str2 = "foo100bar10baz0.txt"
; #PB_String_Equal ; 0 wenn String1 gleich String2 ist
; #PB_String_Lower ; -1 wenn String1 kleiner als String2 ist
; #PB_String_Greater ; 1 wenn String1 größer als String2 ist
Debug NaturalCompareString(@str1, @str2)
Debug NaturalCompareString(@str2, @str1)