Natural_string_compare

=Natural string compare= Natural or Human-friendly sort. Actually, NaturalCompare function that could be used for sort. And usage demo. Demo uses bubble sort - if you need it faster, there is a qsort example in JB folder.

Main difference - if it finds a numbers, it compares them as numbers (so 6 goes before 1000).

code format="lb" 'Natural string compare (caring for numbers in-string) 'function and demo

'Link provided by Rod 'http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html 'Example from page linked to it - 'http://www.davekoelle.com/alphanum.html

'count demo words i = 0 while c$<>"xyzzy" i = i+1 read c$ wend n = i-1

'dim and fill array. dim w$(n) restore for i = 1 to n   read c$    w$(i)=c$ next

print "***************************************************" print "Initial array" for i = 1 to n   print i, w$(i) next

'bubble sort for i = n-1 to 1 step -1 for j = 1 to i       if w$(j)>w$(j+1) then t$=w$(j):w$(j)=w$(j+1):w$(j+1)=t$ end if   next next

print "***************************************************" print "Array after native JB sort" for i = 1 to n   print i, w$(i) next

'bubble sort with NaturalCompare function for i = n-1 to 1 step -1 for j = 1 to i       if NaturalCompare(w$(j),w$(j+1))=1 then t$=w$(j):w$(j)=w$(j+1):w$(j+1)=t$ end if   next next

print "***************************************************" print "Array after Natural sort" for i = 1 to n   print i, w$(i) next

end

'*************************************************** 'Natural string compare (caring for numbers in-string) 'returns -1 0 1 as C strcmp 'Then sorting, condition 'NaturalCompare(w$(j),w$(j+1))=1 is to be used instead of w$(j)>w$(j+1)

function NaturalCompare(s1$,s2$) if s1$=s2$ then NaturalCompare=0: exit function l1=len(s1$) l2=len(s2$) minLen=l1 if minLen>l2 then minLen=l2 prevFirstDigit1=0 prevFirstDigit2=0 for i=1 to minLen c1$=mid$(s1$,i,1) isDigit1=instr("0123456789",c1$)<>0 c2$=mid$(s2$,i,1) isDigit2=instr("0123456789",c2$)<>0 'should use prev first digit pos 'or prev first NON-ZERO digit pos 'if we would not ignore leading zeros. if c1$<>c2$ then if isDigit1=0 AND isDigit2=0 then NaturalCompare=(c1$>c2$)*2-1     'sign exit function else 'real fun if prevFirstDigit1 =0 and prevFirstDigit2 =0 _ and NOT(isDigit1 AND isDigit2) then NaturalCompare=(c1$>c2$)*2-1     'sign exit function end if               'else at least one of them stays on a number if prevFirstDigit1 =0 then prevFirstDigit1=i 'and we should find last digit as well lastDidit=i while lastDiditval(lastD2$))*2-1 end if           exit function end if       if isDigit1 then if prevFirstDigit1=0 then prevFirstDigit1=i else prevFirstDigit1=0 end if       if isDigit2 then if prevFirstDigit2=0 then prevFirstDigit2=i else prevFirstDigit2=0 end if

next 'if we are here then first string ended, and we already checked for equal - so   NaturalCompare=(len(s1$)>len(s2$))*2-1 end function

'============================== DATA "1000X Radonius Maximus" DATA "200X Radonius" DATA "Allegia 500 Clasteron" DATA "40X Radonius" DATA "20X Radonius" DATA "Alpha 2" DATA "10X Radonius" DATA "20X Radonius Prime" DATA "30X Radonius" DATA "Allegia 51 Clasteron" DATA "Xiph Xlater 40" DATA "Allegia 6R Clasteron" DATA "Alpha 100" DATA "Callisto Morphamax 5000" DATA "Alpha 200" DATA "Allegia 50B Clasteron" DATA "Alpha 2A" DATA "Alpha 2A-8000" DATA "Alpha 2A-900" DATA "Callisto Morphamax" DATA "Allegia 50 Clasteron" DATA "Callisto Morphamax 500" DATA "Xiph Xlater 50" DATA "Callisto Morphamax 600" DATA "Xiph Xlater 500" DATA "Callisto Morphamax 6000 SE2" DATA "Callisto Morphamax 7000" DATA "Xiph Xlater 10000" DATA "Xiph Xlater 2000" DATA "Callisto Morphamax 700" DATA "Xiph Xlater 300" DATA "Xiph Xlater 5" DATA "Callisto Morphamax 6000 SE" DATA "Xiph Xlater 5000" DATA "Xiph Xlater 58" DATA "xyzzy" code