Sorting numbers and text together

Just starting out? Need help? Post your questions and find answers here.
spacewalker
User
User
Posts: 19
Joined: Tue Apr 27, 2010 4:35 pm
Location: Germany

Sorting numbers and text together

Post by spacewalker »

Hello,

I need to sort a text that contains leading numbers.
One problem is that the "numbers" may or may not have padded, leading zeros or an empty string..

So for example I have an array with strings like this

Code: Select all

a$(0) = "100,test1.txt"
a$(1) = "10 test2.txt"
a$(2) = "200test3.txt"
a$(3) = "20	test4.txt"   ;tabulator
If I sort this using sortArray I get this:

Code: Select all

a$(0) = "10 test2.txt"
a$(1) = "100,test1.txt"
a$(2) = "20	test4.txt"
a$(3) = "200test3.txt"
However I would like to sort by the leading numbers' value so the result should be:

Code: Select all

a$(0) = "10 test2.txt"
a$(1) = "20	test4.txt"
a$(2) = "100,test1.txt"
a$(3) = "200test3.txt"
I am thinking to use a second "helper" array b() that contains the numbers for the actual sorting and then sort a$() somehow "synchronously" :

Code: Select all

a$(0) = "100,test1.txt"
a$(1) = "10 test2.txt"
a$(2) = "200test3.txt"
a$(3) = "20	test4.txt"   ;tabulator

b(0)  = 100
b(1)  = 10
b(2)  = 200
b(3)  = 20
Now I can sort b() using SortArray() - but how would I sort a$() accordingly?

thanks
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Sorting numbers and text together

Post by Little John »

Hi,

the easiest way is to create a corresponding structure, and the use SortStructuredArray:

Code: Select all

EnableExplicit

Macro SortStrucArray (_ArrayName_, _Options_, _Structure_Field_)
   ; This macro simplifies usage of the built-in function SortStructuredArray().
   SortStructuredArray(_ArrayName_, _Options_, OffsetOf(_Structure_Field_), TypeOf(_Structure_Field_))
EndMacro


Structure MySortStruc
   text$
   value.i
EndStructure   


Define i.i, lastElement.i=3
Dim a.MySortStruc(lastElement)

a(0)\text$ = "100,test1.txt"
a(1)\text$ = "10 test2.txt"
a(2)\text$ = "200test3.txt"
a(3)\text$ = "20   test4.txt"

For i = 0 To lastElement
   a(i)\value = Val(a(i)\text$)
Next

SortStrucArray(a(), #PB_Sort_Ascending, MySortStruc\value)

For i = 0 To lastElement
   Debug a(i)\text$
Next
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Sorting numbers and text together

Post by PB »

> I would like to sort by the leading numbers' value

Just posted a nice procedure for you here:

http://www.purebasic.fr/english/viewtop ... 40&t=57819

:)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
spacewalker
User
User
Posts: 19
Joined: Tue Apr 27, 2010 4:35 pm
Location: Germany

Re: Sorting numbers and text together

Post by spacewalker »

Little John wrote:Hi,

the easiest way is to create a corresponding structure, and the use SortStructuredArray:
thank you,that works

@PB:
Thank you fo your answer.
As you said, your code is OK for small arrays..but slow for large arrays.

Here is my procedure based on Little John's code. It sorts 1 million lines in 10 seconds or so:

Code: Select all

EnableExplicit

Procedure ArraySort_Numericstring( array output.s(1) )

Structure MySortStruct
   text.s
   value.l
EndStructure 

Macro SortStrucArray (_ArrayName_, _Options_, _Structure_Field_)
   ; This macro simplifies usage of the built-in function SortStructuredArray().
   SortStructuredArray(_ArrayName_, _Options_, OffsetOf(_Structure_Field_), TypeOf(_Structure_Field_))
EndMacro

Protected i.l
Protected lastElement.l = ArraySize (output() )
protected Dim a.MySortStruct(lastElement)         ;helper structure 




For i = 0 To lastElement
   a(i)\text  = output (i)
   a(i)\value = val ( output (i)) ;Val (a(i)\text ) faster ?
next


SortStrucArray(a(), #PB_Sort_Ascending, MySortStruct\value)
 


for i=0 to LastElement
  output (i) = a(i)\text
next
  
 

EndProcedure


dim output.s(1000000)
define i.l

;simulate array with 1 million elements
for i=0 to 1000000
  output(i) = str (Random(1000000)) + " .Line xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
next
  

For i = 0 To 20 ;the first lines before sorting
    Debug output(i)
Next
debug "------------------------------------------"


;sort them  
ArraySort_Numericstring (output())


;result
For i = 0 To 20 ;the first lines after sorting
    Debug output(i)
Next


thanks for your answers
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Sorting numbers and text together

Post by wilbert »

This should be a bit faster

Code: Select all

Procedure SortNumericStrings(Array ArrayToSort.s(1))
  
  Structure SortNumericStrings
    value.i
    *string
  EndStructure
  
  Protected *tmp.Integer, i.i, arraySize.i = ArraySize(ArrayToSort())
  
  Dim tmp.SortNumericStrings(arraySize)
    
  For i = 0 To arraySize
    tmp(i)\value = Val(ArrayToSort(i))
    tmp(i)\string = @ArrayToSort(i)
  Next
  
  SortStructuredArray(tmp(), #PB_Sort_Ascending, 0, #PB_Integer)
  *tmp = @ArrayToSort()
  
  For i = 0 To arraySize
    *tmp\i = tmp(i)\string
    *tmp + SizeOf(Integer)
  Next
  
EndProcedure
Windows (x64)
Raspberry Pi OS (Arm64)
spacewalker
User
User
Posts: 19
Joined: Tue Apr 27, 2010 4:35 pm
Location: Germany

Re: Sorting numbers and text together

Post by spacewalker »

wilbert wrote:This should be a bit faster
very nice... according to my tests it's 10x faster :-)

thank you
Post Reply