Sign in to follow this  
Followers 0
Luigi

Someone have a best way to sort an array 2D by the first line?

9 posts in this topic

#1 ·  Posted (edited)

Hi Forum!

I write this little code, to order an array by the first line, this main's point, the first line (or line 0) have any label name, each col means a label's data.

The others is a data.

Like this (example):

+--+--+

|bb|aa|

+--+--+

|22|11|

+--+--+

Then build a array with labels (aa, bb), sort, and change the columns by the sort result:

After sort:

+--+--+

|aa|bb|

+--+--+

|11|22|

+--+--+

Someone have a best way to do this?

#include <Array.au3>

Local $arr[][3] = [ _
        ['cField', 'aField', 'bField'], _
        ['333', '111', '222'] _
        ]

_ArrayTec($arr)

Func _ArrayTec(ByRef $arr)
    _ArrayDisplay($arr, 'before sort')
    __ArrayTecSort($arr)
    _ArrayDisplay($arr, 'after sort')
EndFunc   ;==>_ArrayTec

Func __ArrayTecSort(ByRef $arr)
    Local $col[UBound($arr, 2)][3]
    For $ii = 0 To UBound($arr, 2) - 1
        $col[$ii][0] = $arr[0][$ii]
        $col[$ii][1] = $ii
    Next
    Local $old = $col
    _ArraySort($old, 1)
    For $ii = 0 To UBound($arr, 2) - 1
        $col[$ii][1] = $old[$ii][2]
    Next

    For $ii = 0 To UBound($arr, 2) - 1
        _ArraySwap($arr, $old[$ii][1], $old[$ii][2], True)
    Next
EndFunc   ;==>__ArrayTecSort

Br, Detefon!

Edited by Detefon

m(o.O)m

Share this post


Link to post
Share on other sites



I would transpose the array (switch rows and columns) by using _ArrayTranspose, sort the array with _ArraySort and then transpose the array again.

Never tried it myxself so I don't know how fast this approach is.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

@water, I never try _ArrayTranspose, very interesting... I will try, thank you!

Edited by Detefon

m(o.O)m

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

For small arrays does not have diference...
With small arrays, above 50 lines, is notable.

_ArraySortMethodOne(2,2)= 0.292023906830606
_ArraySortMethodTwo(2,2)= 0.191301020851811
_ArraySortMethodOne(5,2)= 0.232966962893399
_ArraySortMethodTwo(5,2)= 0.315211909358098
_ArraySortMethodOne(10,2)= 0.262676591131748
_ArraySortMethodTwo(10,2)= 0.733320579931943
_ArraySortMethodOne(50,2)= 0.230793087656447
_ArraySortMethodTwo(50,2)= 13.8305565700307
_ArraySortMethodOne(100,2)= 0.230793087656447
_ArraySortMethodTwo(100,2)= 54.7367292163035
_ArraySortMethodOne(2,5)= 0.613395129360069
_ArraySortMethodTwo(2,5)= 0.491658116090735
_ArraySortMethodOne(5,5)= 0.655785696480641
_ArraySortMethodTwo(5,5)= 0.517382306394671
_ArraySortMethodOne(10,5)= 0.571004562239497
_ArraySortMethodTwo(10,5)= 1.07715517990991
_ArraySortMethodOne(50,5)= 0.474267114195115
_ArraySortMethodTwo(50,5)= 15.1765476542437
_ArraySortMethodOne(100,5)= 0.531512495434862
_ArraySortMethodTwo(100,5)= 56.2569926320122
_ArraySortMethodOne(2,10)= 1.17896500350719
_ArraySortMethodTwo(2,10)= 1.13621212384712
_ArraySortMethodOne(5,10)= 1.30432514217144
_ArraySortMethodTwo(5,10)= 1.34236795881811
_ArraySortMethodOne(10,10)= 1.72098456258732
_ArraySortMethodTwo(10,10)= 1.66627536912402
_ArraySortMethodOne(50,10)= 1.14563224987392
_ArraySortMethodTwo(50,10)= 16.8366637101963
_ArraySortMethodOne(100,10)= 0.989113232813342
_ArraySortMethodTwo(100,10)= 61.129009350562
#include <Array.au3>
#include <File.au3>


Local $aSize[][2] = [ _
        [2, 2], _
        [5, 2], _
        [10, 2], _
        [50, 2], _
        [100, 2], _
        [2, 5], _
        [5, 5], _
        [10, 5], _
        [50, 5], _
        [100, 5], _
        [2, 10], _
        [5, 10], _
        [10, 10], _
        [50, 10], _
        [100, 10] _
        ]

Local $aTest, $aOne, $aTwo, $time1, $time2, $start

For $ii = 0 To UBound($aSize, 1) - 1
    $aTest = _ArrayGenerator($aSize[$ii][0], $aSize[$ii][1])
    $aOne = $aTest
    $aTwo = $aTest

    $start = TimerInit()
    _ArraySortMethodOne($aOne)
    $time1 = TimerDiff($start)
    ConsoleWrite("_ArraySortMethodOne(" & $aSize[$ii][0] & "," & $aSize[$ii][1] & ")= " & $time1 & @LF)

    $start = TimerInit()
    _ArraySortMethodTwo($aTwo)
    $time2 = TimerDiff($start)
    ConsoleWrite("_ArraySortMethodTwo(" & $aSize[$ii][0] & "," & $aSize[$ii][1] & ")= " & $time2 & @LF)


Next



;~ _ArraySortMethodOne($try1)
;~ _ArrayDisplay($try1, "_ArraySortMethodOne[ " & TimerDiff($start) & "ms ]")


;~ $start = TimerInit()
;~ _ArraySortMethodTwo($try2)
;~ _ArrayDisplay($try2, "_ArraySortMethodOne[ " & TimerDiff($start) & "ms ]")

Func _ArraySortMethodTwo(ByRef $arr)
    _ArrayTranspose($arr)
    _ArraySort($arr)
    _ArrayTranspose($arr)
EndFunc   ;==>_ArraySortMethodTwo

Func _ArraySortMethodOne(ByRef $arr)
    Local $col[UBound($arr, 2)][3]
    For $ii = 0 To UBound($arr, 2) - 1
        $col[$ii][0] = $arr[0][$ii]
        $col[$ii][1] = $ii
    Next
    Local $old = $col
    _ArraySort($old, 1, 0, 0, 0)
    For $ii = 0 To UBound($arr, 2) - 1
        $col[$ii][1] = $old[$ii][2]
    Next

    For $ii = 0 To UBound($arr, 2) - 1
        _ArraySwap($arr, $old[$ii][1], $old[$ii][2], True)
    Next
EndFunc   ;==>_ArraySortMethodOne

Func _ArrayGenerator($lin = 2, $col = 2)
    Local $arr[$lin][$col]
    For $ii = 0 To UBound($arr, 1) - 1
        For $jj = 0 To UBound($arr, 2) - 1
            Switch $ii
                Case 0
                    $arr[$ii][$jj] = __RandomName()
                Case Else
                    $arr[$ii][$jj] = StringFormat("%06s", Random(0, 999999, 1))
            EndSwitch
        Next
    Next
    Return $arr
EndFunc   ;==>_ArrayGenerator

Func __RandomName()
    Local $string
    For $ii = 0 To 15
        $string &= Chr(Random(65, 90, 1))
    Next
    Return $string
EndFunc   ;==>__RandomName
Edited by Detefon

m(o.O)m

Share this post


Link to post
Share on other sites

Seens to be ease of coding vs. speed :)


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

this way should be quicker (I think) could you check?

#include <Array.au3>

Local $arr[][9] = [ _
        ['cField', 'aField', 'bField', 'fField', 'eField', 'dField', 'gField', 'iField', 'hField'], _
        ['333', '111', '222', "666", "555", "444", "777", "999", "888"], _
        ['333', '111', '222', "666", "555", "444", "777", "999", "888"], _
        ['333', '111', '222', "666", "555", "444", "777", "999", "888"], _
        ['333', '111', '222', "666", "555", "444", "777", "999", "888"] _
        ]

_ArrayTec($arr)

Func _ArrayTec(ByRef $arr)
    _ArrayDisplay($arr, 'before sort')
    __ArrayTecSort($arr)
    _ArrayDisplay($arr, 'after sort')
EndFunc   ;==>_ArrayTec

Func __ArrayTecSort(ByRef $arr)
    Local $aNDX[UBound($arr, 2)][2]
    For $i = 0 To UBound($arr, 2) - 1
        $aNDX[$i][0] = $arr[0][$i] ; extract first row
        $aNDX[$i][1] = $i ; and set index pre sorting
    Next
    _ArraySort($aNDX) ; sort first row
    $aTemp = $arr ; clone $arr to $aTemp
    For $i = 0 To UBound($arr, 1) - 1 ; scan all rows
        For $ii = 0 To UBound($arr, 2) - 1 ; scan all columns
            $arr[$i][$ii] = $aTemp[$i][$aNDX[$ii][1]] ; rebuild $arr using $aNDX as index
        Next
    Next
EndFunc   ;==>__ArrayTecSort

edit

used a little bigger array

Edited by Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

Great idea to first sort the header row and then re-arrange the data columns :thumbsup:


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Great idea to first sort the header row and then re-arrange the data columns :thumbsup:

thanks :)


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I improved my first _ArrayTec...

#include <Array.au3>
#include <File.au3>

; $aSize contain the spec's random array
; create an array with $aSize[$lines][$columns]
Local $aSize[][2] = [ _
        [2, 2], _
        [5, 2], _
        [10, 2], _
        [50, 2], _
        [100, 2], _
        [2, 5], _
        [5, 5], _
        [10, 5], _
        [50, 5], _
        [100, 5], _
        [2, 10], _
        [5, 10], _
        [10, 10], _
        [50, 10], _
        [100, 10] _
        ]

Local $aTest, $time, $start

For $ii = 0 To UBound($aSize, 1) - 1
    ; create an array: _ArrayGenerator($lines, $colums)
    $aTest = _ArrayGenerator($aSize[$ii][0], $aSize[$ii][1])

    $start = TimerInit() ; start time of sorting
    _ArrayTecSort($aTest)
    $time = TimerDiff($start) ; end time of sorting
    ConsoleWrite("_ArraySortByHeader(" & $aSize[$ii][0] & "," & $aSize[$ii][1] & ")= " & $time & "ms to sorting" & @LF)
Next

Func _ArrayTecSort(ByRef $arr)
    Local $aIndexUnsort = __ArrayHeader($arr)
    Local $aIndexSort = __ArrayHeader($arr, 1)

    Local $aFrom[1]
    Local $aTo[1]
; verify is $aFrom and $aTo is the same postion, if yes, not nothing
; verify if $aTo[?] is in $aFrom[?], if yes, not nothing
; verify if $aFrom[?] is in $aTo[?], if yes, not nothing
    For $ii = 0 To UBound($arr, 2) - 1
        If Not ($aIndexSort[$ii] == $aIndexUnsort[$ii]) And (_ArraySearch($aFrom, $aIndexSort[$ii]) == -1) And (_ArraySearch($aTo, $aIndexUnsort[$ii]) == -1) Then
            _ArrayAdd($aFrom, _ArraySearch($arr, $aIndexUnsort[$ii], 0, 0, 0, 0, 0, 0, True))
            _ArrayAdd($aTo, _ArraySearch($arr, $aIndexSort[$ii], 0, 0, 0, 0, 0, 0, True))
        EndIf
    Next
    For $ii = 1 To UBound($aFrom, 1) - 1
        _ArraySwap($arr, $aFrom[$ii], $aTo[$ii], True)
    Next
EndFunc   ;==>_ArraySortByHeader

Func __ArrayHeader($arr, $mode = 0)
    Local $ret[1]
    For $ii = 0 To UBound($arr, 2) - 1
        _ArrayAdd($ret, $arr[0][$ii])
    Next
    _ArrayDelete($ret, 0)
    If $mode Then _ArraySort($ret)
    Return $ret
EndFunc   ;==>__ArrayHeader

Func _ArrayGenerator($lin = 2, $col = 2)
    Local $arr[$lin][$col]
    For $ii = 0 To UBound($arr, 1) - 1
        For $jj = 0 To UBound($arr, 2) - 1
            Switch $ii
                Case 0
                    $arr[$ii][$jj] = __RandomName()
                Case Else
                    $arr[$ii][$jj] = StringFormat("%06s", Random(0, 999999, 1))
            EndSwitch
        Next
    Next
    Return $arr
EndFunc   ;==>_ArrayGenerator

Func __RandomName()
    Local $string
    For $ii = 0 To 15
        $string &= Chr(Random(65, 90, 1))
    Next
    Return $string
EndFunc   ;==>__RandomName
Edited by Detefon

m(o.O)m

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