Jump to content

[Help] Sorting 2 Dimensional array using 2 Columns


Recommended Posts

I have this array sorted using column 1 and here is how it looks like:

Posted Image

I want to sort the columns based on this priority

->Column 1 Ascending then Column 2 Descending

Here is how it should be:

[0]|antique lids|2.01|104

[1]|antique lidt|2.01|27

[2]|pot with lid|2.33|284

[3]|pot and lid|2.52|27

[4]|bears grease pot lid|2.55|155

[5]|lids pots|2.79|27

[6]|lid pot|2.88|237

[7]|ceramic pot with lid|2.92|22

[8]|ceramic pot lid|3.01|27

[9]|pot lids for sale|3.30|43

Do Not Steal The Government Hates CompetitionO2JAM AutoPlayBot [|||||.............] 10%Friendster Commenter [..................] 0%Auto Message Download Percentage [|||||||||||||||||] 100%
Link to comment
Share on other sites

I wrote this to sort multi dim arrays:

#include <Array.au3>
Dim $array [10][3] = [["antique lids", 2.01, 104], _
             ["antique lidt", 2.01, 27], _
             ["pot with lid", 2.01, 284], _
             ["pot and lid", 2.52, 27], _
             ["bears grease pot lid", 2.55, 155], _
             ["lids pots", 2.79, 27], _
             ["lid pot", 2.88, 237], _
             ["ceramic pot with lid", 2.92, 22], _
             ["ceramic pot lid", 3.01, 27], _
             ["pot lids for sale", 3.30, 43]]

Dim $aI[3]
$aI[0] = 1 ;sort column 2 then
$aI[1] = 2 ;sort column 3 and last
$aI[2] = 0 ;sort column 1


_ArraySort_MultiColumn($array, $aI, 0)
_ArrayDisplay($array, 'Nachher:')
For $i = 0 To UBound($array) - 1
    ConsoleWrite($array[$i][0] & "|" & $array[$i][1] & "|" & $array[$i][2] & @CRLF)
Next

; #FUNCTION# =============================================================================
; Name...........:  _ArraySort_MultiColumn
; Description ...:  sorts an array at given colums (multi colum sort)
; Syntax.........:  _ArraySort_MultiColumn(ByRef $aSort, ByRef $aIndices)
; Parameters ....:  $aSort - array to sort
;       $aIndices - array with colum indices which should be sorted in
;                               specified order
;                   $dir - sort direction - if set to 1, sort descendingly
; Autor .........:  UEZ
; Version .......:  v0.60 build 2010-07-04 Beta
; =========================================================================================
Func _ArraySort_MultiColumn(ByRef $aSort, ByRef $aIndices, $oDir = 0, $iDir = 0)
    Local $1st, $2nd
    If Not IsArray($aIndices) Or Not IsArray($aSort) Then ;checks if $aIndices is an array
        Return SetError(1, 0, 0) ;no array
    EndIf
    If UBound($aIndices) > UBound($aSort, 2) Then ;check if $aIndices array is greater the $aSort array
        Return SetError(2, 0, 0) ;$aIndices array is greater
    EndIf
    Local $x
    For $x = 0 To UBound($aIndices) - 1 ;check if array content makes sense
        If Not IsInt($aIndices[$x]) Then
            Return SetError(3, 0, 0) ;array content is not numeric
        EndIf
    Next
    If UBound($aIndices) = 1 Then ;check if only one index is given
        Return _ArraySort($aSort, $oDir, 0, 0, $aIndices[0])
    EndIf
    Local $j, $k, $l = 0
    _ArraySort($aSort, $oDir, 0, 0, $aIndices[0])
    Do
        $1st = $aIndices[$l]
        $2nd = $aIndices[$l + 1]
        $j = 0
        $k = 1
        While $k < UBound($aSort)
            If $aSort[$j][$1st] <> $aSort[$k][$1st] Then
                If $k - $j > 1 Then
                    _ArraySort($aSort, $iDir , $j, $k - 1, $2nd)
                    $j = $k
                Else
                    $j = $k
                EndIf
            EndIf
            $k += 1
        WEnd
        If $k - $j > 1 Then _ArraySort($aSort, $oDir, $j, $k, $2nd)
        $l += 1
    Until $l = UBound($aIndices) - 1
    Return SetError(0, 0, 1)
EndFunc

Maybe it is usable for you, too.

BR,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • Moderators

geocine,

You need to look for matching entries in the first column and then sort just those values on the second column. Here is a script showing how to do that - I changed your array so it has another matching but unsorted pair at the end for demonstration purposes: :P

#include <Array.au3>

Global $aArray[10][3] = [ _
["antique lids",2.01,104], _
["antique lids",2.01,27], _
["pot with lid",2.33,284], _
["pot and lid",2.52,27], _
["bears grease pot lid",2.55,155], _
["lids pots",2.79,27], _
["lid pot",2.88,237], _
["ceramic pot with lid",2.92,22], _
["ceramic pot lid",3.30,127], _
["pot lids for sale",3.30,43]]

_ArrayDisplay($aArray, "Before")

_Second_Sort($aArray)

_ArrayDisplay($aArray, "After")

Func _Second_Sort(ByRef $aArray)

    Local $aTemp

    ; Work through array
    For $i = 0 To UBound($aArray) - 1
        ; Get already sorted value of Col 1
        $iValue = $aArray[$i][1]
        ; Now see if there are any other entries with the same value
        For $j = $i To UBound($aArray) - 1
            If $aArray[$j][1] <> $iValue Then ExitLoop
        Next
        ; If there are then sort the array for those entries only
        If $j - $i > 1 Then
            _ArraySort($aArray, 0, $i, $j - 1, 2)
            ; Move the loop index to the next entry
            $i = $j
        EndIf
    Next

EndFunc

I hope that helps. ;)

M23

Edit:

UEZ,

Apologies - I had not seen your post. Awesome display by the Turniermannschaft this afternoon by the way. :blink:

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

@UEZ

Where can I specify sorting direction. Is it possible to specify different sorting directions for different columns.

I want the first index to be sorted ASC and the second to be sorted DESC.

Thanks,

Edit:

I tried your function using this code and I get this result for three identical rows on column 1:

Dim $aI[2]
        $aI[0] = 1
        $aI[1] = 2
        _ArraySort_MultiColumn($KEYWORDS, $aI)

Posted Image

Edited by geocine
Do Not Steal The Government Hates CompetitionO2JAM AutoPlayBot [|||||.............] 10%Friendster Commenter [..................] 0%Auto Message Download Percentage [|||||||||||||||||] 100%
Link to comment
Share on other sites

...

UEZ,

Apologies - I had not seen your post. Awesome display by the Turniermannschaft this afternoon by the way. :blink:

Why you are apologies? ;) Many roads lead to Rome...

Yep, I hope Germany will win :P Currently best "Turniermannschaft" in this tournament!

@UEZ

Where can I specify sorting direction. Is it possible to specify different sorting directions for different columns.

I want the first index to be sorted ASC and the second to be sorted DESC.

Thanks,

I updated the code with your values! No, it is not implemented yet to sort the indicies seperately in different directions!

BR,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

@UEZ

Hi, I updated my post. I am trying to sort for column 1[ASC] and 2[DESC] in order. Please see the result above whenever I have 3 rows with the same column value for column 1.

Do Not Steal The Government Hates CompetitionO2JAM AutoPlayBot [|||||.............] 10%Friendster Commenter [..................] 0%Auto Message Download Percentage [|||||||||||||||||] 100%
Link to comment
Share on other sites

Please check post#2 again!

I used strings instead of float/int! That's the reason for the sort results!

BR,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

@UEZ

Hi for some reason I still get the same result for column three on post number #4.

104

27

284

Should be

284

104

27

Thanks,

Do Not Steal The Government Hates CompetitionO2JAM AutoPlayBot [|||||.............] 10%Friendster Commenter [..................] 0%Auto Message Download Percentage [|||||||||||||||||] 100%
Link to comment
Share on other sites

As I mentioned before it is not implemented yet to sort the indicies seperately in different directions!

Here the result for :

Dim $aI[3]

$aI[0] = 1 ;sort column 2 then

$aI[1] = 2 ;sort column 3 and last

$aI[2] = 0 ;sort column 1

antique lidt|2.01|27

antique lids|2.01|104

pot with lid|2.01|284

pot and lid|2.52|27

bears grease pot lid|2.55|155

lids pots|2.79|27

lid pot|2.88|237

ceramic pot with lid|2.92|22

ceramic pot lid|3.01|27

pot lids for sale|3.3|43

Other direction:

pot lids for sale|3.3|43

ceramic pot lid|3.01|27

ceramic pot with lid|2.92|22

lid pot|2.88|237

lids pots|2.79|27

bears grease pot lid|2.55|155

pot and lid|2.52|27

pot with lid|2.01|284

antique lids|2.01|104

antique lidt|2.01|27

BR,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • Moderators

geocine,

Did you see my post a while ago? You have to sort the array twice, but it does get you what you said you wanted! :blink:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Hi Melba23

I think your code is right, could you check what is wrong with my code. Because, every time I enter the array values manually on your code it works perfectly.

Your Code [Modified With My Values | Manually Inputted Array]

#include <Array.au3>

Global $aArray[10][3] = [ _
        ["ceramic pot with lid", 2.92, 22], _
        ["lid pot", 2.88, 237], _
        ["bears grease pot lid", 2.55, 155], _
        ["ceramic pot lid", 3.01, 27], _
        ["pot lids for sale", 3.30, 43], _
        ["antique lidt", 2.01, 27], _
        ["pot with lid", 2.01, 284], _
        ["lids pots", 2.79, 27], _
        ["antique lids", 2.01, 104], _
        ["pot and lid", 2.52, 27]]

_ArraySort($aArray, 0, 0, 0, 1)

_ArrayDisplay($aArray, "Before")

_Second_Sort($aArray)

_ArrayDisplay($aArray, "After")


Func _Second_Sort(ByRef $aArray)

    Local $aTemp

    ; Work through array
    For $i = 0 To UBound($aArray) - 1
        ; Get already sorted value of Col 1
        $iValue = $aArray[$i][1]
        ; Now see if there are any other entries with the same value
        For $j = $i To UBound($aArray) - 1
            If $aArray[$j][1] <> $iValue Then ExitLoop
        Next
        ; If there are then sort the array for those entries only
        If $j - $i > 1 Then
            ;Change to Descending
            _ArraySort($aArray, 1, $i, $j - 1, 2)
            ; Move the loop index to the next entry
            $i = $j
        EndIf
    Next
EndFunc   ;==>_Second_Sort

Your Code [using My Generated Array]

#include <Array.au3>
#include <String.au3>
#include <Inet.au3>
$domain = "amazon.com"
$keyword = "pot lids"
$api_key = "7ce8efe1e5a0685b941918a6909456ab"

$objKeyArray = ObjCreate("Scripting.Dictionary")
$KEYWORD_PROPOSAL = _INetGetSource("http://us.api.semrush.com/?action=report&type=phrase_related&phrase=" & $keyword & "&key=" & $api_key & "&display_limit=10&export=api")
If (StringInStr($KEYWORD_PROPOSAL, "ERROR") < 1) Then
    $KEYWORD_PROPOSALS = _StringExplode($KEYWORD_PROPOSAL, @LF)
    Global $KEYWORD_PROPOSALS_EXPLODED[10][3]
    For $i = 1 To 10 Step 1
        $KEYWORD_PROPOSAL_ROW = _StringExplode($KEYWORD_PROPOSALS[$i], ";")
        ;For $j = 0 to 6 Step 1
        ;   $KEYWORD_PROPOSALS_EXPLODED[$i][$j] = $KEYWORD_PROPOSAL_ROW[$j]
        ;Next

        If $i = 6 Then
            $KEYWORD_PROPOSALS_EXPLODED[$i - 1][0] = "antique lidt"
        Else
            $KEYWORD_PROPOSALS_EXPLODED[$i - 1][0] = $KEYWORD_PROPOSAL_ROW[0]
        EndIf

        If $i = 6 Or $i = 7 Then
            $KEYWORD_PROPOSALS_EXPLODED[$i - 1][1] = 2.01
        Else
            $KEYWORD_PROPOSALS_EXPLODED[$i - 1][1] = $KEYWORD_PROPOSAL_ROW[3]
        EndIf

        $KEYWORD_PROPOSALS_EXPLODED[$i - 1][2] = $KEYWORD_PROPOSAL_ROW[5]
    Next
    Dim $aI[2]
    $aI[0] = 1
    $aI[1] = 2
    
    _ArraySort($KEYWORD_PROPOSALS_EXPLODED, 0, 0, 0, 1)]
    _ArrayDisplay($KEYWORD_PROPOSALS_EXPLODED,"Before")
    _Second_Sort($KEYWORD_PROPOSALS_EXPLODED)
    _ArrayDisplay($KEYWORD_PROPOSALS_EXPLODED,"After")
    $KeywordList = ObjCreate("System.Collections.ArrayList")
Else
    $KEYWORD_PROPOSAL = 0
EndIf

Func _Second_Sort(ByRef $aArray)

    Local $aTemp

    ; Work through array
    For $i = 0 To UBound($aArray) - 1
        ; Get already sorted value of Col 1
        $iValue = $aArray[$i][1]
        ; Now see if there are any other entries with the same value
        For $j = $i To UBound($aArray) - 1
            If $aArray[$j][1] <> $iValue Then ExitLoop
        Next
        ; If there are then sort the array for those entries only
        If $j - $i > 1 Then
            ;Change to Descending
            _ArraySort($aArray, 1, $i, $j - 1, 2)
            ; Move the loop index to the next entry
            $i = $j
        EndIf
    Next
EndFunc   ;==>_Second_Sort

I think there is an issue regarding references. Kindly take a quick look on my code.

Edited by geocine
Do Not Steal The Government Hates CompetitionO2JAM AutoPlayBot [|||||.............] 10%Friendster Commenter [..................] 0%Auto Message Download Percentage [|||||||||||||||||] 100%
Link to comment
Share on other sites

Replace line

$KEYWORD_PROPOSALS_EXPLODED[$i - 1][2] = $KEYWORD_PROPOSAL_ROW[5]

with

$KEYWORD_PROPOSALS_EXPLODED[$i - 1][2] = Int($KEYWORD_PROPOSAL_ROW[5])

and it should work!

Here the version with my function adjusted for your requirement

#include <Array.au3>
#include <String.au3>
#include <Inet.au3>
$domain = "amazon.com"
$keyword = "pot lids"
$api_key = "7ce8efe1e5a0685b941918a6909456ab"

$objKeyArray = ObjCreate("Scripting.Dictionary")
$KEYWORD_PROPOSAL = _INetGetSource("http://us.api.semrush.com/?action=report&type=phrase_related&phrase=" & $keyword & "&key=" & $api_key & "&display_limit=10&export=api")
If (StringInStr($KEYWORD_PROPOSAL, "ERROR") < 1) Then
    $KEYWORD_PROPOSALS = _StringExplode($KEYWORD_PROPOSAL, @LF)
    Global $KEYWORD_PROPOSALS_EXPLODED[10][3]
    For $i = 1 To 10 Step 1
    $KEYWORD_PROPOSAL_ROW = _StringExplode($KEYWORD_PROPOSALS[$i], ";")
    ;For $j = 0 to 6 Step 1
    ; $KEYWORD_PROPOSALS_EXPLODED[$i][$j] = $KEYWORD_PROPOSAL_ROW[$j]
    ;Next

    If $i = 6 Then
    $KEYWORD_PROPOSALS_EXPLODED[$i - 1][0] = "antique lidt"
    Else
    $KEYWORD_PROPOSALS_EXPLODED[$i - 1][0] = $KEYWORD_PROPOSAL_ROW[0]
    EndIf

    If $i = 6 Or $i = 7 Then
    $KEYWORD_PROPOSALS_EXPLODED[$i - 1][1] = 2.01
    Else
    $KEYWORD_PROPOSALS_EXPLODED[$i - 1][1] = $KEYWORD_PROPOSAL_ROW[3]
    EndIf

    $KEYWORD_PROPOSALS_EXPLODED[$i - 1][2] = Int($KEYWORD_PROPOSAL_ROW[5])
    Next
    Dim $aI[2]
    $aI[0] = 1
    $aI[1] = 2
    _ArraySort_MultiColumn($KEYWORD_PROPOSALS_EXPLODED, $aI, 0)
    _ArrayDisplay($KEYWORD_PROPOSALS_EXPLODED,"After")
    $KeywordList = ObjCreate("System.Collections.ArrayList")
Else
    $KEYWORD_PROPOSAL = 0
EndIf

; #FUNCTION# =============================================================================
; Name.............:    _ArraySort_MultiColumn
; Description ...:      sorts an array at given colums (multi colum sort)
; Syntax...........:    _ArraySort_MultiColumn(ByRef $aSort, ByRef $aIndices)
; Parameters ...:       $aSort - array to sort
;                       $aIndices - array with colum indices which should be sorted in specified order - zero based
;                       $oDir/$iDir - sort direction - if set to 1, sort descendingly else ascendingly
; Author .........:     UEZ
; Version ........:     v0.70 build 2013-11-20 Beta
; =========================================================================================
Func _ArraySort_MultiColumn(ByRef $aSort, ByRef $aIndices, $oDir = 0, $iDir = 0)
    If Not IsArray($aIndices) Or Not IsArray($aSort) Then Return SetError(1, 0, 0) ;checks if $aIndices is an array
    If UBound($aIndices) > UBound($aSort, 2) Then Return SetError(2, 0, 0) ;check if $aIndices array is greater the $aSort array
    Local $1st, $2nd, $x, $j, $k, $l = 0
    For $x = 0 To UBound($aIndices) - 1 ;check if array content makes sense
        If Not IsInt($aIndices[$x]) Then Return SetError(3, 0, 0) ;array content is not numeric
    Next
    If UBound($aIndices) = 1 Then Return _ArraySort($aSort, $oDir, 0, 0, $aIndices[0]) ;check if only one index is given
    _ArraySort($aSort, $oDir, 0, 0, $aIndices[0])
    Do
        $1st = $aIndices[$l]
        $2nd = $aIndices[$l + 1]
        $j = 0
        $k = 1
        While $k < UBound($aSort)
            If $aSort[$j][$1st] <> $aSort[$k][$1st] Then
                If $k - $j > 1  Then
                    _ArraySort($aSort, $iDir , $j, $k - 1, $2nd)
                    $j = $k
                Else
                    $j = $k
                EndIf
            EndIf
            $k += 1
        WEnd
        If $k - $j > 1 Then _ArraySort($aSort, $iDir, $j, $k, $2nd)
        $l += 1
    Until $l = UBound($aIndices) - 1
    Return 1
EndFunc

BR,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

@UEZ

Wow thanks. Thank you for spontaneously answering my inquiries and almost spoon feeding me glad to have you here.

Thanks,

Aivan

Do Not Steal The Government Hates CompetitionO2JAM AutoPlayBot [|||||.............] 10%Friendster Commenter [..................] 0%Auto Message Download Percentage [|||||||||||||||||] 100%
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...