Sign in to follow this  
Followers 0
VeeDub

ArraySort

13 posts in this topic

Hi,

I would like to sort a two dimensional array using arraysort but I'm finding the help hard to follow, would appreciate someone who is familiar with the function to advise the syntax I should use.

The array elements / "columns" are 0 and 1, both of which are strings. Ideally I would like to sort by column 0 and then column 1.

Even if I just do this

_ArraySort($Array)

just to get some output.

I get the error

Array.au3 (565) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:

Thanks

VW

Share this post


Link to post
Share on other sites



Hi,

I had not realised thtat the helpfile had no examples of 2d sort; but it does work!

If you want subsort, for more than 1 column, you will need my 'subsort" command;

Get the UDF from link in my signature array2d.au3

Example there shows use of subsort... ? has a 2d sort on 1 col example too.. not sure

best., Randall

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Looks like if you have a 2D array, you have to define the optional values. You may not have to define all of them, but that worked for me. Also, make sure that your array variable has been defined as Global - that has helped me with the array functions in the past.

Edited by bluebearr

BlueBearrOddly enough, this is what I do for fun.

Share this post


Link to post
Share on other sites

Looks like if you have a 2D array, you have to define the optional values. You may not have to define all of them, but that worked for me. Also, make sure that your array variable has been defined as Global - that has helped me with the array functions in the past.

Hi bluebearr,

You are quite possibly right, but I look at the help and I don't understand the options. There seems to be assumed knowledge here, which is not a good thing with help.

Perhaps you can help me with the options I need to specify?

I have a 2d array called: array. The array has two columns 0 and 1.

e.g.

Field1 = array[$row][0]

Field2 = array[$row][1]

So to sort this array I should specify:

_arraysort(array,1,0,?,?,?)

array = the array that I want to sort

1 = I want the array to be sorted in descending order

$i-Base : I think I use this to specify that I want to sort on the first column - which in this instance is column 0

$i-UBound : ?

$i-Dim : ?

$i-SortIndex : ? ... is this where I specify the second sort column?

This is doing my head in :whistle:

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Hi,

Try this example and look at the output and commands;

#include <Array.au3>
Opt("TrayIconDebug", 1)
Dim $aArr[10][5] ; Array
for $i=0 to 9
    for $j=0 to 4
        $aArr[$i][$j]=round(Random($i+$j))
    next
Next
lf_Array2dDisplay($aArr, "$output b4 sort", 0)
;_ArraySort ( ByRef $a_Array, [$i_Descending[, $i_Base=0[, $i_Ubound=0[, $i_Dim=1[, $i_SortIndex=0]]]]] )
_ArraySort($aArr, 0, 0, -1, UBound($aArr,2), UBound($aArr,2) -1)
lf_Array2dDisplay($aArr, "$output after sort ASC, last column; '_ArraySort($aArr, 0, 0, -1, UBound($aArr,2), UBound($aArr,2) -1)'", 0)
_ArraySort($aArr, 1, 0, -1, UBound($aArr,2), 0)
lf_Array2dDisplay($aArr, "$output after sort DESC, first col '_ArraySort($aArr, 1, 0, -1, UBound($aArr,2), 0'", 0)
_ArraySort($aArr, 0, 0, -1, UBound($aArr,2), 1)
lf_Array2dDisplay($aArr, "$output after sort ASC col2 (index1) '_ArraySort($aArr, 0, 0, -1, UBound($aArr,2), 1'", 0)
_ArraySort($aArr, 1, 0, 5, UBound($aArr,2), 1)
lf_Array2dDisplay($aArr, "$output after sort DESC col2 (index1) (only 5 rows) '_ArraySort($aArr, 0, 0,5, UBound($aArr,2), 1'", 0)
Exit
Func lf_Array2dDisplay(ByRef $ar_Array, $s_Title="Array contents", $n_Index=1,$i_Message=0)
    ; Display 2 dimensional array
    Local $output = ""
    Local $r, $c
    If Not IsArray($ar_Array) Then Return -1
    For $r = $n_Index to UBound($ar_Array,1) - 1
        $output = $output & @LF
        For $c = 0 to UBound($ar_Array,2) - 1
            $output = $output & $ar_Array[$r][$c] & " "
        Next
    Next
    ConsoleWrite( $s_Title&"="&@LF&$output&@LF)
    if $i_Message then MsgBox(4096, $s_Title, $output)
    Return $output
EndFunc   ;==>lf_Array2dDisplay

But you did NOT read my other post ; you CANNOT subsort on a second column unless you use my UDF.

You have not downloaded the UDF and examples.

If you want subsort, for more than 1 column, you will need my 'subsort" command;

Get the UDF from link in my signature array2d.au3

Example there shows use of subsort..

array = the array that I want to sort

1 = I want the array to be sorted in descending order CORRECT

$i-Base : NOT=>"I think I use this to specify that I want to sort on the first column" - NO! "STARTROW to sort"

$i-UBound : "NUMBER OF ROWS" to sort

$i-Dim : Number items in the 2nd dimension (ubound(arr,2)-1) that you wish to sort; usually all COLUMNS?

$i-SortIndex : ... this where I specify the ONLY sort column ****

Best, Randall Edited by randallc

Share this post


Link to post
Share on other sites

Hi Randallc,

Thanks for your example and the explaination of the inputs, I've had another look at the help, and I think your example and explanation of the parameters ought to be in the help instead of what is there. :whistle:

If you want subsort, for more than 1 column, you will need my 'subsort" command;

Get the UDF from link in my signature array2d.au3

Example there shows use of subsort

If I want to sort the array by column 2 and then column 1, I have tried the following
$i_ColSortIndex="2|1";,[numbered by base 1 (ie first col number is "1")]
_Array2D1DFieldSortSt($Array,$i_ColSortIndex)

But when I try to write the sorted array back out to a file

$Results = FileOpen(@ScriptDir & "\" & $Results_File,2)
For $Array_Count = 0 To $Array_Total
  FileWriteLine($Results,$Array[$Array_Count][0] & " " & $Array[$Array_Count][1])
Next    
FileClose($Results)

I get error

Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
on the FileWriteLine statement. The error occurs on the first pass of the loop ($Count = 0).

I guess I am doing something wrong with the sort.

VW

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Hi,

No you're OK; the sort comes back as 1D array of delimited strings;

then;

_ArrayDisplay($Array,"$ar_TempSingle")
$ar2D_Array=_Array2DCreateFromArraySt($Array)oÝ÷ ٩ݶ§±éݶayø¥y¼ªºtߦ«Ø0+­¬ªºR¢ºòܲz-rW®)íç±jjey©h¶è¦Ø¨Æ«yÊ&éíyÚ.)íç±jjey·¬¶¶§u©ez®¶­sc´f7E7V%6÷'C$F"æS2%ó#·&æFÆÆ0¢6æ6ÇVFRgV÷Cµô'&fWs$CBæS2gV÷C²°¢b33c¶õ&÷w3Ó#S³³¦Æö6Âb33c¶%õFV×6ævÆU²b33c¶õ&÷w2³ÒÂb33c¶#%ô'&³Õ³Ð¦f÷"b33c¶ÓFòb33c¶õ&÷w2 b33c¶%õFV×6ævÆU²b33c¶ÓÒb33c¶fײgV÷C·ÆÆæRgV÷C²f×·&÷VæB&æFöÒÓÂÂófײgV÷C·ÆÖ÷&UògV÷C²f×´6"&æFöÒ62gV÷C¶gV÷C²Â62gV÷C·¢gV÷C²Âf×´6"&æFöÒ62gV÷C¶gV÷C²Â62gV÷C·¢gV÷C²Âf×µ7G&ær&æFöÒÓÂÂfײgV÷C·ÇÂgV÷C²f×·&÷VæB&æFöÒÓÂÂófײgV÷C·ÂgV÷C²¦æW@£³ÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓТb33c¶%ó$D'&Õô'&$D7&VFTg&öÔ'&7Bb33c¶%õFV×6ævÆRâb33c¶ô6öÅ6÷'DæFWÒgV÷C³'ÂÓWÃ2gV÷C³²Å¶çVÖ&W&VB'&6RRf'7B6öÂçVÖ&W"2gV÷C³gV÷C²Òµ6÷'G2öâ6öÇ2"ÃRÃ2´DU42öâR2äTtDdWÕУ³ÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÐ¥ô'&$CDfVÆE6÷'E7Bb33c¶%ó$D'&Âb33c¶ô6öÅ6÷'DæFWµô'&$CDfVÆE6÷'E7C²6÷'B$B'&¦bb33c¶õ&÷w2fÇC³FVâô'&F7Æb33c¶%ó$D'&ÂgV÷C²b33c¶%õFV×6ævÆRgV÷C²¢b33c¶#5ô'&Õô'&$D7&VFTg&öÔ'&7Bb33c¶%ó$D'&¢b33c¶õ&W7VÇG2ÒfÆT÷Vâ67&DF"fײgV÷C²b3#µ&W7VÇG5ôfÆRçGBgV÷C²Ã"¤f÷"b33c´'&ô6÷VçBÒFòT&÷VæBb33c¶#5ô'&Ó¢fÆUw&FTÆæRb33c¶õ&W7VÇG2Âb33c¶#5ô'&²b33c´'&ô6÷VçEÕ³ÒfײgV÷C²gV÷C²fײb33c¶#5ô'&²b33c´'&ô6÷VçEÕ³EÒ¤æWB¤fÆT6Æ÷6Rb33c¶õ&W7VÇG2¥'VåvBgV÷C¶æ÷FWBæWRgV÷C²f×´67&DF"fײgV÷C²b3#µ&W7VÇG5ôfÆRçGBgV÷C²
[EDIT does not change function..?] Edited by randallc

Share this post


Link to post
Share on other sites

Hi,

Unfortunately these additions didn't work for me, when I look at the results from the _ArrayDisplay my array is completely scrambled - the contents are missing.

_ArrayDisplay($Array,"$ar_TempSingle")

$ar2D_Array=_Array2DCreateFromArraySt($Array)

So I thought I would try and work through your most recent example to understand how it works.

I tried adding the statement

_ArrayDisplay($ar_2DArray,"$ar_TempSingle")
so that I could view the 2D array before it is sorted, because I wanted to compare your input 2D array to mine to see if there are input requirements for the sort to work properly.

So your code looks like this

$ar_2DArray=_Array2DCreateFromArraySt($ar_TempSingle,0)
_ArrayDisplay($ar_2DArray,"$ar_TempSingle")
$i_ColSortIndex="2|-5|3"

But when I do that the program bombs out - do you know why this would be?

Second, if I understand the sort index argument correctly, in the example you are sorting by columns: 2, 5-descending and column 3.

But I thought if I had a 2D array, then I would only have 2 columns, so if you have 5 columns then it looks like you have a 5D array.

And when you write out the results to a file

FileWriteLine($h_Results,$ar3_Array[$Array_Count][1] & " " & $ar3_Array[$Array_Count][4])

you're outputting array elements 1 and 4 which again indicates to me that you're working with a 5D array (as a 5D array would have elements 0, 1, 2, 3, 4).

So this leads me to the question, does the way the subsort algorithm operates, require it to use a 5D "working array" to sort a 2D array?

Thanks

VW

Share this post


Link to post
Share on other sites

You seem a bit confused!

It is YOUR line "FileWriteLine($h_Results,$ar3_Array[$Array_Count][1] & " " & $ar3_Array[$Array_Count][4])"

Surely you know that the second bracket after the array[][] gives the element NUMBER in the 2nd dimension, not the 4th or 5th dimension!

1. Please post your script with array so I can fix it and show you;

2. Surely my example ran OK and worked!?

Best, Randall

Share this post


Link to post
Share on other sites

1. Please post your script with array so I can fix it and show you;

Best, Randall

Hi,

It's not practical to upload my data, but this routine produces output that is representative of my data

$Rows = 25
    $Columns = 2
    Dim $Array[$Rows][$Columns]
    $output = ""
        
    For $Row = 0 To $Rows-1
        $field1 = ""
        $field2 = ""
        For $i = 1 to 15
            $field1 = $field1 & Chr(Random(Asc("a"), Asc("z"), 1))
            $field2 = $field2 & Chr(Random(Asc("A"), Asc("Z"), 1))
        Next    
        $Array[$Row][0] = $field1
        $Array[$Row][1] = $field2
        $output = $output & $Row & ". " & $Array[$Row][0] & " " & $Array[$Row][1] & @LF 
    Next
    
    MsgBox(0,"Contents",$output)

You seem a bit confused!

It is YOUR line "FileWriteLine($h_Results,$ar3_Array[$Array_Count][1] & " " & $ar3_Array[$Array_Count][4])"

Surely you know that the second bracket after the array[][] gives the element NUMBER in the 2nd dimension, not the 4th or 5th dimension!

You're right I should have gone through your code this morning rather than last night after returning from the pub, clearly my thinking was a bit off ... hope my driving on the way home was OK. :whistle:

Having said that the FileWriteLine above is NOT my code, this was my code:

$Results = FileOpen(@ScriptDir & "\" & $Results_File,2)
For $Array_Count = 0 To $Array_Total
  FileWriteLine($Results,$Array[$Array_Count][0] & " " & $Array[$Array_Count][1])
Next    
FileClose($Results)

But you're right, my analysis of your code was flawed. Hopefully it will all become clear to me once I see how this 2D array is sorted. I must admit this has turned out to be more involved than I anticipated.

Thanks for your patience.

VW

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Hi,

Here it is with your array; [but there are no duplicates in the first column, so you can't see any subsort in the second column - see 2nd example, which is really what you meant (unless I misinterpret you!)]

;arrayveedub.au3
#include "_ArrayView2D1D.au3" ;
local $Rows = 25, $Columns = 2,$Array[$Rows][$Columns], $output = ""
For $Row = 0 To $Rows-1
    For $i = 1 to 15
        $Array[$Row][0] &= Chr(Random(Asc("a"), Asc("z"), 1))
        $Array[$Row][1]&=  Chr(Random(Asc("A"), Asc("Z"), 1))
    Next
    $output &= $Row & ". " & $Array[$Row][0] & " " & $Array[$Row][1] & @LF
Next
MsgBox(0,"Contents",$output)
;=======================================
$i_ColSortIndex="1|-2";,[numbered by base 1 (ie first col number is "1")] [Sorts on cols 2,5,3 {DESC on 5 as NEGATIVE}]
_Array2D1DFieldSortSt($Array,$i_ColSortIndex);_Array2D1DFieldSortSt; sort 2D array
if $Rows<100 then 
    _ArrayDisplay($Array,"$ar_TempSingle")
Else
    _ArrayView2D1D($Array,"$ar_TempSingle")
endif
$ar3_Array=_Array2DCreateFromArraySt($Array)
$h_Results = FileOpen(@ScriptDir & "\Results_File.txt",2)
For $Array_Count = 0 To UBound($ar3_Array)-1
    FileWriteLine($h_Results,$ar3_Array[$Array_Count][0] & " " & $ar3_Array[$Array_Count][1])
Next
FileClose($h_Results)
RunWait("notepad.exe "&@ScriptDir & "\Results_File.txt")
Best, Randall Edited by randallc

Share this post


Link to post
Share on other sites

Very good.

FWIW your 2D sort is faster on my data than the built-in arraysort.

Cheers,

VW

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Very good.

FWIW your 2D sort is faster on my data than the built-in arraysort.

Cheers,

VW

Yes, If you look at my UDF, you will see I have used vbs to try to speed it up.

I got to thinking perhaps you really DID want to sort each column individually; I think you'd have to pull each one out and sort it, then plunk it back in the 2D array; like so;

;arrayveedubSortIndiv.au3  0_3 [if you really want to sort EACH colmn completely and separately AFTER making Array2D;]
#include "_GUICtrlListView.au3" ;_108
#include "Array2D.au3"
local $Rows = 25, $Columns = 2,$Array[$Rows][$Columns], $output = ""
For $Row = 0 To $Rows-1
    For $i = 1 to 15
        $Array[$Row][0] &= Chr(Random(Asc("a"), Asc("z"), 1))
        $Array[$Row][1]&=  Chr(Random(Asc("A"), Asc("Z"), 1))
    Next
    $output &= $Row & ". " & $Array[$Row][0] & " " & $Array[$Row][1] & @LF
Next
MsgBox(0,"Contents",$output)
;=======================================
for $i_ColumnNumber= 0 to UBound($Array,2)-1
    $ArrayColumn=_Array2DToD($Array , "Array contents", 0, $i_ColumnNumber, 1)
    _ArraySort($ArrayColumn)
    _ArrayReplace2DColumn( $Array, $ArrayColumn, $i_ColumnNumber)
next
;=======================================
$h_Results = FileOpen(@ScriptDir & "\Results_File.txt",2)
For $Array_Count = 0 To UBound($Array)-1
    FileWriteLine($h_Results,$Array[$Array_Count][0] & " " & $Array[$Array_Count][1])
Next
FileClose($h_Results)
RunWait("notepad.exe "&@ScriptDir & "\Results_File.txt")
Best, Randall Edited by randallc

Share this post


Link to post
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
Sign in to follow this  
Followers 0