I imagine that a revisit of this topic at some point will be in order. Until then, enjoy the much improved get_median function:

**************************************************************

* The following code is an improved get_median *

**************************************************************

FUNCTION get_median_clean

LPARAMETERS tnType, teName, teColDel

*-- boundary checking

IF !BETWEEN(tnType,1,3)

RETURN 0

ENDIF

DO CASE

CASE tnType = 1 .and. VARTYPE(teName)<>"C"

RETURN 0

CASE tnType = 1 .and. (!ISDIGIT(teName) .or.;

VARTYPE(teColDel)<>"C")

RETURN 0

CASE INLIST(tnType,2,3) .and. VARTYPE(teColDel)<>"N"

RETURN 0

CASE tnType = 2 .and. (!USED(teName) .or. ;

EMPTY(FIELD(teColDel,teName)))

RETURN 0

CASE tnType = 2 .and. ;

VARTYPE(EVALUATE(FIELD(teColDel,teName))) <> "N"

RETURN 0

CASE tnType = 3 .and. ;

VARTYPE(EVALUATE(teColDel[1,teColDel])) <> "N"

RETURN 0

ENDCASE

*-- local declerations

LOCAL lcSelCol AS String

LOCAL lnItems, lnHalf, lnInc AS Integer

LOCAL lnMedian AS Number

*-- create the aMedian Array

DO CASE

CASE tnType = 1 && use a delimted string

lnItems = ALINES( aMedian , STRTRAN(teName ,teColDel,CHR(13)) )

FOR lnInc = 1 TO lnItems

aMedian[lnInc] = VAL(aMedian[lnInc])

NEXT

CASE tnType = 2 && calculate using an alias

lcSelCol = FIELD(teColDel,teName)

lcSQL = "SELECT " + lcSelCol + " FROM " + teName + ;

" ORDER BY " + lcSelCol + " INTO ARRAY aMedian"

&lcSQL

lnItems= _TALLY

CASE tnType = 3 && calculate using an array

lnItems= ALEN(&teName,1)

DIMENSION aMedian[lnItems]

FOR lnInc = 1 TO lnItems

aMedian[lnInc] = &teName.[lnInc,teColDel]

NEXT

ENDCASE

*-- find the median

ASORT(aMedian)

lnHalf = CEILING( lnItems / 2)

IF MOD(lnHalf,2) = 0

lnMedian = ( aMedian[lnHalf] + aMedian[lnHalf+1] ) / 2

ELSE

lnMedian = aMedian[lnHalf]

ENDIF

RETURN lnMedian

ENDFUNC

## No comments:

Post a Comment