SortArray

See Also: Array Functions, Array Variable Assignments, Working with Arrays

Purpose

Returns array with sorted elements.

Return Type

Array

Syntax

Simple Sort:
(SortArray( {ArrayId} [, {bLinguistic} ] ) )
Extended Sort:

    (SortArray( {ArrayId} [, {ObjectId} , {MessageId} ] )

Where:

What it Does

SortArray sorts an array using either an internal sorting algorithm or one provided by the developer.

 

The simple sort style lets the runtime do all the work, while the expanded style requires that you create a function to do the comparison.

You can use the simple search style for arrays of any simple data type and arrays of structs where the first struct member is a simple data type.

If the short style of the function is used with an array, a smart comparison will be applied where the first member of the struct will be used for the comparison. Assuming that the first member is a simple data type (String, Integer, etc., not a struct or array), the comparison will be applied on that member based on the data type of that first member. Not only does this simplify coding, it allows the runtime to perform all comparisons without sending messages, which is much faster.

DataFlex implements different sorting algorithms for different data types in the runtime, in order to provide developers with the most efficient comparison method based on the data type. Algorithms provided in the runtime will also run faster. To use the internal comparison algorithms, simply do not pass the optional ObjectId and MessageId parameters. We recommend the use of these internal algorithms whenever there is no strong reason for a developer to use a special comparison.

Binary vs Linguistic

For comparing strings DataFlex implements two styles of comparisons. By default (second parameter bLinguistic is not passed or True) a linguistic comparison is done according to the localization rules configured by DF_LOCALE_CODE. This results in a logical sorting order for humans. When sorting for the computer (for example to be able to quickly find items using BinarySearchArray) it is recommended to use the binary comparison method that simply compares the individual code units. This is done by passing false as the second parameter. The resulting order might not be logical for humans (extended characters might be located in strange places) but makes perfect sense to computers.

Custom Comparison Function for Extended Sort

The developer has the option of providing a custom comparison function for the sorting process if a custom function is desired or required (for arrays of variant and struct arrays where the search cannot use the first struct member or needs to search for multiple struct members).

The function provided in {MessageId} must follow the following syntax:

Function MyCompareFunc {array-element-type} arg1 {array-element-type} arg2 Returns Integer

This function must return one of these values:

You can use a single custom comparison function for a specific data type for all array functions that require one (BinarySearchArray, BinarySearchInsertPos, CountArray, MinArray, MaxArray, SearchArray, SortArray).

 

Simple Array Sort

You can use the simple sort style to sort arrays of simple data types or arrays of structs where the first struct member is a simple type.

Example

String array sort:

This sample sorts a dynamic array of strings (sCustomers), then displays the sorted array to the screen.

The code that populates the sCustomers array is not shown for the sake of simplicity and clarity.

// fires when the button is clicked

Procedure OnClick

    String[] sCustomers

 

    // populate sCustomers with customer data

    // :

 

    // sort the array

    Move (SortArray(sCustomers)) to sCustomers

End_Procedure

Example

Case-insensitive string array sort:

Sorting a string array in a case-insensitive manner is a common task, so the runtime provides a predefined function for case-insensitive string comparison: DFSTRICMP, defined in the Desktop object.

Syntax

(SortArray( {ArrayId} , Desktop , (RefFunc(DFSTRICMP)) ))

This sample sorts a dynamic array of strings (sCustomers) in a case-insensitive manner, then displays the sorted array to the screen.

The code that populates the sCustomers array is not shown for the sake of simplicity and clarity.

// fires when the button is clicked

Procedure OnClick

    String[] sCustomers

    Integer i iArrayCount

 

    // populate sCustomers with customer data

    // :

 

    // sort the array in a case-insensitive manner

    Move (SortArray(sCustomers, Desktop, (RefFunc(DFSTRICMP)))) to sCustomers

 

    // display the sorted array

    Move (SizeOfArray(sCustomers)) to iArrayCount

    For i From 0 to (iArrayCount-1)

        showln sCustomers[i]

    Loop

End_Procedure

Simple Struct Array Sort:

You can use the simple sort style for arrays of any simple data type and arrays of structs where the first struct member is a simple data type.

If the short style of the function is used with an array, a smart comparison will be applied where the first member of the struct will be used for the comparison. Assuming that the first member is a simple data type (String, Integer, etc., not a struct or array), the sort will be applied on that member based on the data type of that first member. Not only does this simplify coding, it allows the runtime to perform all comparisons without sending messages, which is much faster.

Example

This sample shows how to sort an array of friends by last name.

This sample sorts an array of structs by last name, by simply making last name the first member of the struct. By not passing the optional ObjectId and MessageId parameters, the runtime attempts to sort the array by the first struct member, which happens to be a simple type (String).

Struct tFriend

    String Last

    String First

End_Struct

 

Procedure OnClick

    // declare array of tFriend structs

    tFriend[] MyFriends

 

    // fill MyFriends array

    Move "Janet"     to MyFriends[0].First

    Move "Smith"     to MyFriends[0].Last

    Move "Pedro"     to MyFriends[1].First

    Move "Rodriguez" to MyFriends[1].Last

    Move "Judy"      to MyFriends[2].First

    Move "Smith"     to MyFriends[2].Last

    Move "Fred"      to MyFriends[3].First

    Move "Jones"     to MyFriends[3].Last

    Move "Martin"    to MyFriends[4].First

    Move "Anderson"  to MyFriends[4].Last

    Move "Michael"   to MyFriends[5].First

    Move "Schmidt"   to MyFriends[5].Last

    Move "Jacques"   to MyFriends[6].First

    Move "Verne"     to MyFriends[6].Last

    Move "Enrico"    to MyFriends[7].First

    Move "Ricci"     to MyFriends[7].Last

    Move "Karl"      to MyFriends[8].First

    Move "Sorensen"  to MyFriends[8].Last

    Move "Juan"      to MyFriends[9].First

    Move "Garcia"    to MyFriends[9].Last

 

    Move (SortArray(MyFriends)) to MyFriends

End_Procedure

 

Example

Extended struct array sort:

This sample declares a structured data type (tUSAddress), then declares 2 arrays of type tUSAddress. The first array (myAddresses) is populated, then sorted, and the result placed in the second array (mySortedAddresses), the contents of which are displayed to the screen. A custom comparison function is used to determine how array elements are compared.

Since this example does a comparison of the second struct member, not the first, simple search cannot be used and a custom comparison function must be used instead.

This sample is somewhat contrived, since the obvious solution to make this particular sort more efficient would be  to simply make ZipCode the first struct member, but the point is to demonstrate how to use a custom function for sorting.

You can make the custom comparison function as complex as you need, as long as it returns EQ, LT or GT to the SortArray call.

Struct tUSAddress

    String Street

    Integer ZipCode

End_Struct

 

// Custom comparison function:

//   Returns (GT) struct value in first parameter > struct value in second parameter.

//   Returns (LT) struct value in first parameter < struct value in second parameter.

//   Otherwise returns (EQ).

Function CompareAddresses tUSAddress Address1 tUSAddress Address2 Returns Integer

    If (Address1.ZipCode > Address2.ZipCode) ;

        Function_Return (GT)

    If (Address1.ZipCode < Address2.ZipCode) ;

        Function_Return (LT)

 

    Function_Return (EQ)

End_Function

 

// fires when the button is clicked

Procedure OnClick

    tUSAddress[] myAddresses mySortedAddresses

 

    // initialize address array

    Move 33186 to myAddresses[0].ZipCode

    Move "14001 SW 119 Ave" to myAddresses[0].Street

    Move 33186 to myAddresses[1].ZipCode

    Move "14000 SW 119 Ave" to myAddresses[1].Street

    Move 78664 to myAddresses[2].ZipCode

    Move "514 Paladin Place" to myAddresses[2].Street

    Move 78664 to myAddresses[3].ZipCode

    Move "504 Dinge Bay" to myAddresses[3].Street

    Move 78664 to myAddresses[4].ZipCode

    Move "504 Paladin Place" to myAddresses[4].Street

 

    Move (SortArray(myAddresses, Self, (RefFunc(CompareAddresses)))) to mySortedAddresses

End_Procedure

Example

Struct array sort sorting multiple members:

This sample is identical to the example directly above, with the exception that it sorts the addresses first by zip code and then by street address, so that street addresses are sorted by street address inside each batch of sorted zip codes.

The only code change required for this is to add a second set of conditional statements to the custom sort function that compares the street addresses the same way as the zip codes. This function tests the ZipCode and Street members in the arrays in order of precedence.

// Custom comparison function:

//   Returns (LT) if ZipCode member value in first parameter < ZipCode member value value in second parameter.

//   Returns (GT) if ZipCode member value in first parameter > ZipCode member value value in second parameter.

//   Returns (LT) if Street member value in first parameter < Street member value value in second parameter.

//   Returns (GT) if Street member value in first parameter < Street member value value in second parameter.

//   Otherwise returns (EQ).

Function CompareAddresses tUSAddress Address1 tUSAddress Address2 Returns Integer

    // sort first by zip code

    If (Address1.ZipCode > Address2.ZipCode) ;

        Function_Return (GT)

    If (Address1.ZipCode < Address2.ZipCode) ;

        Function_Return (LT)

 

    // sort second by street address

    If (Address1.Street > Address2.Street) ;

        Function_Return (GT)

    If (Address1.Street < Address2.Street) ;

        Function_Return (LT)

 

    Function_Return (EQ)

End_Function

Example

Sorting a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional integer array and fills it with 9 (3x3) elements of unsorted integer values. This creates an array as such:

    7 5 2

    4 6 1

    9 7 2

The first "row" (row 0) of the array is then sorted and placed in row 0 of the resulting array (in this sample, the results of SortArray are placed back in the original array), resulting in this array:

    2 5 7

    4 6 1

    9 7 2

Procedure OnClick

    Integer[][] myInts

 

    Move 7 to myInts[0][0]

    Move 5 to myInts[0][1]

    Move 2 to myInts[0][2]

    Move 4 to myInts[1][0]

    Move 6 to myInts[1][1]

    Move 1 to myInts[1][2]

    Move 9 to myInts[2][0]

    Move 7 to myInts[2][1]

    Move 2 to myInts[2][2]

    

    Move (SortArray(myInts[0])) to myInts[0]

End_Procedure

Sorting and Searching via RowId

You can search and sort on RowId. This affects SearchArray(), BinarySearchArray(), CountArray()and SortArray(). The sort order of RowIds has no real meaning and its actual sort order is undefined. The reason for sorting RowIds is it can allow faster searching when used with BinarySearchArray().

Notes

a) Using internal logic:

b) Using a developer supplied comparison method: