Jump to content

Sorting


lesmly
 Share

Recommended Posts


I have a problem - I'd be able to write it but using a very large number of IF, and maybe it is a much simpler way?

I have a two-dimensional table:
in the first row is a number from 1 to 7
in the second row: numerical value (an integer from 0 inclusive to... not know). It happens that one or more
of these values are empty - then I can take any value, eg. negative. And now I have to sort of the second
line from the smallest to the largest, and blank values at the end. Of course, numbers from first row must also be appropriately
sort.

example:
I have
1         2      3     4     5      6        7
100    30    -1    0     -1     60     100


I want to receive
4   2      6      1         7        3      5 
0   30    60    100    100    -1    -1

Edited by lesmly
Link to comment
Share on other sites

  • Moderators

lesmly,

This seems to work:

#include <Array.au3>

Global $aTable[][] = [[1, 2, 3, 4, 5, 6, 7], [100, 30, -1, 0, -1, 60, 100]]

; Transpose table
_ArrayTranspose($aTable)

;_ArrayDisplay($aTable, "Transposed", Default, 8)

; Sort on second column
_ArraySort($aTable, 1, 0, 0, 1)

;_ArrayDisplay($aTable, "Sorted", Default, 8)

; Reset to original format
_ArrayTranspose($aTable)

_ArrayDisplay($aTable, "Result", Default, 8)

Good enough for what you need?

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

Almost ...

You sort from highest value but I need from lowest exept empty (negative).  

I need:

4   2      6      1         7        3      5 
0   30    60    100    100    -1    -1

Your script:

7     1      6    2  4   3  5 

100 100 60 30 0 -1 -1

Edited by lesmly
Link to comment
Share on other sites

You could try ArrayWorkshop in my signature. I think this does what you want.

#include <ArrayWorkshop.au3>
#include <Array.au3> ; for ArrayDisplay()

Local $aArray = [[1,2,3,4,5,6,7],[100,30,' ',0,' ',60,100]]
_ArrayDisplay($aArray)

Local $aNew[1], $a2
For $i = 0 To UBound($aArray) -1
    $a2 = _ExtractRegion($aArray, 1, $i) ; grab each row
    _ArraySortXD($a2, 2, 2) ; sort numeric (dimension = 2)
    _ArrayAttach($aNew, $a2) ; attach the result to the new array
Next
_DeleteRegion($aNew) ; delete the empty row (that we started with) in $aNew
_ArrayDisplay($aNew)

Edit: I'm assuming the values of -1 are replacements.

Edited by czardas
Link to comment
Share on other sites

Here the beginning of a other solution:

#include <Array.au3>
#include <arraySort2D_MC.au3>

Global $aTable[][] = [[1, 2, 3, 4, 5, 6, 7], [100, 30, -1, 0, -1, 60, 100]]

_arraySort2D_MC($aTable, "1%N|0",0,0,0,False,True)


_ArrayDisplay($aTable, "Result", Default, 8)

therefor needed:

Func _arraySort2D_MC(ByRef $avArray, $ColOrder, $iStart = 0, $iEnd = 0, $iDesc = 0, $bDelDuplictes = False, $bTranspose = False)
    ;Parameterübergabe
    ;$avArray           zu sorterendes Array
    ;$ColdOrder         String mit den Sortieranweisungen, getrennt mit "|" für jede Spalte
    ;                   zulässige Angaben:
    ;                                       nur Spaltenindex = normale Sortierung
    ;                                       Spaltenindex%N = numerische Sortierung
    ;                                       Spaltenindex%D = Sortierung nach Datum JJJJ/MM/TT
    ;                                       Spaltenindex%G = Sortierung nach Geburtstag MM/TT/JJJJ
    ;                   z.B.: "1|2%N|3%D|0" die Reihenfolge für die Sortierung ist 1.,2., 3. 0. (0 basierend)
    ;                   die 1. Spalte wird Standard von _ArraySort verwendet
    ;                   die 2. Spalte (%N) wird bei der Sortierun numerisch behnadelt
    ;                   die 3. Spalte (%D) wird als Datum behandelt
    ;
    ;                   es müssen alle Spalten des Arrays in den Sortieranweisungen vorkommen
    ;$iStart            Zeile bei der die Sortierung beginnt (OPTIONAL)
    ;$iEnd              Zeile bei der die Sortierung endet (OPTIONAL)
    ;$iDesc             Absteigend 1 = JA 0 = NEIN (OPTIONAL)
    ;$bDelDuplictes     nur einmalige Zeilen zulassen   True = Jede Zeile ist einmalig
    ;                                                   False = Es werden alle Zeilen ausgegeben
    ;$bTranspose        nach Zeilen sortieren           True = Sortierung nach Zeilen
    ;                                                   False = Sortierung nach Spalten
    ;                   =====================================================================
    ;Rückgabe:         0 Fehler (nicht alle Spalten in $ColOrder definert
    ;                   1 Erfolg
    ;Autor:             AutoBert 2010 erweeitert 2012
    ;==============================================================================================================
    If $bTranspose Then _ArrayTranspose($avArray)
    Local $iDims = UBound($avArray, 0)
    If @error Or $iDims <> 2 Then
        MsgBox(16, "Fehler:", "kein 2D-Array")
        Return 0
    EndIf
    If $iEnd = 0 Then $iEnd = UBound($avArray) - 1
    If $iEnd > UBound($avArray) - 1 Then $iEnd = UBound($avArray) - 1
    $aCols = StringSplit($ColOrder, "|")
    ;consolewrite($aCols[0] & " " & UBound($array, 2) & @CRLF)
    If $aCols[0] <> UBound($avArray, 2) Then
        MsgBox(16, "Fehler:", "unterschiedliche Spaltenanzahl!")
        Return 0
    EndIf
    Local Const $sLeer = "                                                                                                                                               "
    Local $aColformat = $aCols
    Local $sRow
    For $i = 1 To $aColformat[0]
        ;$aColformat[$i] = StringRight($aColformat[$i], 1)
        $aCols[$i] = StringReplace($aCols[$i], "N", "")
        $aCols[$i] = StringReplace($aCols[$i], "D", "")
    Next
    _ArrayDelete($aColformat, 0)
    _ArrayDelete($aCols, 0)
    Local $iCols = UBound($aColformat)
    For $i = $iStart To $iEnd
        $sRow = ""
        For $j = 0 To $iCols - 1
            $iCol = $aCols[$j]
            Switch StringUpper(StringRight($aColformat[$j], 1))
                Case "N" ;numerisch
                    $aNum = StringSplit($avArray[$i][$iCol], ",")
                    If IsArray($aNum) Then
                        If $aNum[0] = 1 Then _ArrayAdd($aNum, " ")
                        $sRow &= StringRight($sLeer & $aNum[1] & "," & StringLeft($aNum[2]&$sLeer, 30), 99)
                    Else
                        $sRow &= StringRight($sLeer & $aNum[1], 99)
                    EndIf
                Case "D" ;Datum JJJJ/MM/TT
                    ;consolewrite("D: " & $aColformat[$j] & " " &  $avArray[$i][$iCols])
                    $aDate = StringSplit($avArray[$i][$iCol], ".")
                    If IsArray($aDate) Then $sRow &= $aDate[3] & "." & StringRight("0" & $aDate[2], 2) & "." & StringRight("0" & $aDate[1], 2)
                Case "G" ;Geburtstags-Datum MM/TT/JJJJ
                    ;consolewrite("D: " & $aColformat[$j] & " " &  $avArray[$i][$iCols])
                    $aDate = StringSplit($avArray[$i][$iCol], ".")
                    If IsArray($aDate) Then $sRow &= StringRight("0" & $aDate[2], 2) & "." & StringRight("0" & $aDate[1], 2) & "." & $aDate[3]
                Case Else
                    $sRow &= $avArray[$i][$iCol]
            EndSwitch
            If $j <> $iCols - 1 Then $sRow &= "|"
        Next
        $avArray[$i][0] = $sRow
        ;consolewrite($sRow & @CRLF)
    Next
    _ArraySort($avArray, $iDesc, $iStart, $iEnd)
    If $bDelDuplictes Then
        For $i = $iEnd - 1 To $iStart Step -1
            If $avArray[$i][0] = $avArray[$i + 1][0] Then
                _ArrayDelete($avArray, $i + 1)
                $iEnd -= 1
            EndIf
        Next
    EndIf
    ;_ArrayDisplay($avArray)
    ;_ArrayDisplay($aColformat, "FormatStrings")
    ;_ArrayDisplay($aCols, "Cols")
    ;consolewrite($iCols & @CRLF)
    For $i = $iStart To $iEnd
        ;consolewrite($avArray[$i][0] & @CRLF)
        $aSplit = StringSplit($avArray[$i][0], "|", 2)
        For $j = 0 To $iCols - 1
            $iCol = $aCols[$j]
            Switch StringRight($aColformat[$j], 1)
                ;               Case "X"

                ;#cs
                Case "N" ;numerisch
                    $avArray[$i][$iCol] = StringReplace($aSplit[$j], " ", "")
                    if StringRight($avArray[$i][$iCol],1)="," Then $avArray[$i][$iCol] = StringTrimRight($avArray[$i][$iCol], 1)
                    ;consolewrite(" N: " & $avArray[$i][$iCol])
                Case "D" ;Datum JJJJ/MM/TT
                    $aDate = StringSplit($aSplit[$j], ".")
                    $avArray[$i][$iCol] = StringReplace($aDate[3] & "." & $aDate[2] & "." & $aDate[1], "_", "")
                    ;consolewrite(" D: " & $avArray[$i][$iCol])
                Case "G" ;Geburtstags-Datum MM/TT/JJJJ
                    $aDate = StringSplit($aSplit[$j], ".")
                    $avArray[$i][$iCol] = StringReplace($aDate[2] & "." & $aDate[1] & "." & $aDate[3], "_", "")
                    ;consolewrite(" D: " & $avArray[$i][$iCol])
                    ;#ce
                Case Else
                    $avArray[$i][$iCol] = $aSplit[$j]
                    ;consolewrite(" : " & $avArray[$i][$iCol])
            EndSwitch
        Next
        ;consolewrite(@CRLF)
    Next
    If $bTranspose Then _ArrayTranspose($avArray)
    Return 1
    ;_ArrayDisplay($avArray)
EndFunc   ;==>_arraySort2D_MC

but the end of the job, moving <=0 must be done by you.

Edited by AutoBert
transposing moved into udf
Link to comment
Share on other sites

  • Moderators

lesmly,

Not too hard to fix:

#include <Array.au3>

Global $aTable[][] = [[1, 2, 3, 4, 5, 6, 7], [100, 30, -1, 0, -1, 60, 100]]

; Transpose table
_ArrayTranspose($aTable)

; Remove negatives
Local $aNegTable[UBound($aTable)][UBound($aTable, 2)], $iNegIndex = 0
For $i = UBound($aTable) - 1 To 0 Step -1
    If $aTable[$i][1] < 0 Then
        $aNegTable[$iNegIndex][0] = $aTable[$i][0]
        $aNegTable[$iNegIndex][1] = $aTable[$i][1]
        $iNegIndex += 1
        _ArrayDelete($aTable, $i)
    EndIf
Next
; Correct neg table size
ReDim $aNegTable[2][$iNegIndex]

;_ArrayDisplay($aTable, "", Default, 8)
;_ArrayDisplay($aNegTable, "", Default, 8)

; Sort on second column
_ArraySort($aTable, 0, 0, 0, 1)

;_ArrayDisplay($aTable, "Sorted", Default, 8)

; Rejoin arrays
_ArrayConcatenate($aTable, $aNegTable)

; Reset to original format
_ArrayTranspose($aTable)

_ArrayDisplay($aTable, "Result", Default, 8)

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

LOL! I didn't read this carefully enough (or rather I presumed there was a mistake which was incorrect). I was a bit rushed. You only actually need one line of code.

#include <ArrayWorkshop.au3>
#include <Array.au3> ; for ArrayDisplay()

Local $aArray = [[1,2,3,4,5,6,7],[100,30,' ',0,' ',60,100]]
_ArrayDisplay($aArray)

_ArraySortXD($aArray, 2, 2, -1, 1) ; dimension to sort = 2, numeric sort, whole array, sort on 1st dimension index = 1
_ArrayDisplay($aArray)


Edit: If your numbers include numeric strings then you can use this instead:

; dimension to sort = 2 (cols), numeric sort = 2 + (numeric strings = 256), end value = -1, 1st dimension vector index = 1 (2nd row)
_ArraySortXD($aArray, 2, 2 + 256, -1, 1)

 

Edited by czardas
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...