Jump to content

_ArraySort gives ByRef Error

Recommended Posts

I'm trying to write a function that takes a 2D Array and a certain Index to calculate a median of that index

Func _ArrayMedian ($vaArray, $viIndex)
    ; Returns the median of the column of data asked for
    ; Assumes Array sends array dimentions in [0][0] = Rows [0][1] = Columns
    Local $X                                            ; Counter
    Local $vsSum                                        ; Sum of data
    _ArraySort(0, 0, 1, $viIndex)                   ; Sort Array by the index
    If $vaArray[0][0] = 0 Then                          ; Array empty
        Return 0
    ElseIf Mod($vaArray[0][0], 2) = 0 Then                  ; Array has even number
        Return ($vaArray[int(($vaArray[0][0] / 2))][$viIndex] + $vaArray[int($vaArray[0][0] / 2) + 1]][$viIndex) / 2
    Else                                                ; Array has odd number
        Return $vaArray[int($vaArray[0][0] / 2) + 1][$viIndex]

When I do a Syntex check  I get the error

"error: _ArraySort() called with Const or expression on ByRef-param(s)" when I call the _ArraySort() function.

I guess I don't understand what ByRef means so have no idea how to pass my $viIndex value through the function so it looks at the right column. Anyone able to educate me on this?



Link to post
Share on other sites
  • 3 years later...
15 hours ago, GeorgeP said:

this short function got me sorted in no time

The methodology here is still far away from "in no time".
It is not necessary to sort the array completely to calculate the median.
The array only has to be divided step by step into elements larger or smaller than a certain value and if these sub-ranges are treated step by step in the same way, the element in the middle is available at the end. (= "quick select" algorithm)
This way you can calculate the median much faster.

Example script (the required UDF is in the appendix):

#include "Stat_ListFunctions.au3"

; row size of array:
Global Const $N = 1e4 + 1
Global Const $C = 5

; create sample array:
Global $aArray[$N][$C]

For $i = 0 To $N -1
    ; fill only one column with sample data
    $aArray[$i][2] = Random(0, $N, 1)

; copy sample array:
$aArray2 = $aArray

; first method: full sort:
$tTimer = TimerInit()
$iMedian = _Median2DbySorting($aArray, 2)
ConsoleWrite(StringFormat("method:\t%s\nmedian:\t%d\ntime:\t%.1f ms\n\n", "Full sort of array", $iMedian, TimerDiff($tTimer)))

; second method: partition of array
$tTimer = TimerInit()
$iMedian = _Median2DbyPartition($aArray2, 2)
ConsoleWrite(StringFormat("method:\t%s\nmedian:\t%d\ntime:\t%.1f ms\n\n", "partition of array", $iMedian, TimerDiff($tTimer)))

; calculate the median of a column of a 2D-Array by sorting it
Func _Median2DbySorting(ByRef $aArray, $iCol)
    Local Const $N = UBound($aArray)

    _ArraySort($aArray, 0, 0, 0, $iCol)

    Return Mod($N, 2) = 0 ? _
        ($aArray[Int($N/2)][$iCol] + $aArray[Int($N/2) + 1][$iCol]) / 2 : _

; extract the column and calculate the median by partition
Func _Median2DbyPartition(ByRef $aArray, $iCol)
    Local Const $N = UBound($aArray)
    Local $aTmp[$N]
    For $i = 0 To $N - 1
        $aTmp[$i] = $aArray[$i][$iCol]
    Return _stat_Median($aTmp)

produces the following output:


method:    Full sort of array
median:    5018
time:    1552.1 ms

method:    partition of array
median:    5018
time:    77.2 ms



Link to post
Share on other sites
On 8/30/2021 at 8:23 AM, AspirinJunkie said:

The methodology here is still far away from "in no time".

Then again, his “in no time” would appear to relate to his own time sorting out of the problem, not necessarily CPU cycles.

Still, instructive work!

Code hard, but don’t hard code...

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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...