CountArray

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

Purpose

Returns the number of array elements whose value is equal to a test value.

Return Type

Integer

Syntax

Simple Count:
(CountArray( {CompareVal}, {ArrayId} )

Extended Count:
(CountArray( {CompareVal}, {ArrayId}, [{ObjectId}, {MessageId}] ))

Where:

What it Does

Iterates through all elements in an array and compares each element to the passed in value {CompareVal} or uses a custom function for the comparison. The returned count is incremented for each matching element in the array.

 

The simple count 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 count 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 search 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.

 

To determine the element count of one or more dimensions of an array, use SizeOfArray.

To find a specific element in an array, use SearchArray or BinarySearchArray.

 

Custom Comparison Function for Extended Search

The developer has the option of providing a custom comparison function for the counting 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 Count

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

Example

Counting elements in an array of strings:

This sample creates a string array, then adds 10 names, 2 of them being "Smith". When CountArray is called, it returns a count of 2 for the number of array elements being equal to "Smith".

// fires when the button is clicked

Procedure OnClick

    String[] sCustomers

    Integer iCount

 

    Move "Smith" to sCustomers[0]

    Move "Rodriguez" to sCustomers[1]

    Move "Smith" to sCustomers[2]

    Move "Jones" to sCustomers[3]

    Move "Anderson" to sCustomers[4]

    Move "Schmidt" to sCustomers[5]

    Move "Verne" to sCustomers[6]

    Move "Ricci" to sCustomers[7]

    Move "Sorensen" to sCustomers[8]

    Move "Garcia" to sCustomers[9]

 

    // counts the occurrence of "Smith" in sCustomers

    Move (CountArray("Smith", sCustomers)) to iCount

End_Procedure

Example

Case-insensitive count of elements in an array of strings:

Counting elements in 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

(CountArray( {CompareVal}, {ArrayId} , Desktop , (RefFunc(DFSTRICMP)) ))

This sample creates a string array, then adds 10 names, 2 of them being "Smith", but using different casing. When CountArray is called, it returns a count of 2 for the number of array elements being equal to "Smith".

// fires when the button is clicked

Procedure OnClick

    String[] sCustomers

    Integer iCount

 

    Move "Smith" to sCustomers[0]

    Move "Rodriguez" to sCustomers[1]

    Move "smith" to sCustomers[2]

    Move "Jones" to sCustomers[3]

    Move "Anderson" to sCustomers[4]

    Move "Schmidt" to sCustomers[5]

    Move "Verne" to sCustomers[6]

    Move "SMITH" to sCustomers[7]

    Move "Sorensen" to sCustomers[8]

    Move "Garcia" to sCustomers[9]

 

    // counts the occurrence of "smith", in any casing, in sCustomers

    Move (CountArray("Smith", sCustomers, Desktop, (RefFunc(DFSTRICMP)))) to iCount

End_Procedure

 

Simple Struct Array Count:

You can use the simple count 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 search 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 count the number of friends with last name "Smith"in an array filled with 10 tFriend structs.

In Procedure OnClick, MyFriends is declared as a tFriend array and populated with 10 friends' first and last names. Another struct of type tFriend is declared to store the search value (last name "Smith").

By not passing the optional ObjectId and MessageId parameters, the runtime attempts to count the array by the first struct member, which happens to be a simple type (String).

The SearchFriend struct is filled with the value being searched for; since the search only compares the first member (Last) of each struct in the array, there is no need to place values in the other members of this struct.

Struct tFriend

    String Last

    String First

End_Struct

 

Procedure OnClick

    // declare array of 10 tFriend structs

    tFriend[10] MyFriends

 

    // declare tFriend struct that will hold search value

    tFriend SearchFriend

 

    Integer iCount

 

    // 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 value to compare array values to the Comparison struct

    Move "Smith" to SearchFriend.Last

 

    Move (CountArray(SearchFriend, MyFriends)) to iCount

End_Procedure

 

Example

Extended struct array count:

This sample uses a custom comparison function to count how many friends with last name "Smith" and first name "Judy" are in an array of tFriend structs.

Since this example does a comparison of 2 struct members, simple search cannot be used and a custom comparison function must be used instead.

The custom comparison function (CompareFriends) returns EQ only if both the First and Last members of the tFriend struct passed in as the first parameter to the function are equal to the First and Last members of the tFriend struct passed in as the second parameter.

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

In Procedure OnClick, MyFriends is declared as a array of tFriend and populated with friends' names. Another struct of type tFriend is declared to store the comparison value.

The result in iCount will be 1 using the data in this sample.

Struct tFriend

    String First

    String Last

End_Struct

 

// Custom comparison function:

Function CompareFriends tFriend Friend1 tFriend Friend2 Returns Integer

    If ((Friend1.Last = Friend2.Last) and (Friend1.First = Friend2.First)) Begin

        Function_Return (EQ)

    End

End_Function

    

Procedure OnClick

    // declare array of tFriend structs

    tFriend[] MyFriends

 

    // declare tFriend struct that will hold comparison value(s)

    tFriend CompareFriend

 

    Integer iCount

 

    // 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 value to compare array values to the Comparison struct

    Move "Smith" to CompareFriend.Last

    Move "Judy" to CompareFriend.First

 

    // call CompareFriends function to count array elements that match value(s) in CompareFriend

    Move (CountArray(CompareFriend, MyFriends, Self, (RefFunc(CompareFriends)))) to iCount

End_Procedure

Example

Counting a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional string array and fills it with 8 (2x4) elements of unsorted string values. This creates an array as such:

    Smith Rodriguez Scott Jones

    Anderson Smith Verne Ricci

The number of occurrences of "Smith" in the first "row" (row 0) of the array is counted and displayed, then the second "row" (row 1). Last, the total count is displayed.

Procedure OnClick

    String[][] sCustomers

    Integer iCount0 iCount1

 

    Move "Smith"     to sCustomers[0][0]

    Move "Rodriguez" to sCustomers[0][1]

    Move "Scott"     to sCustomers[0][2]

    Move "Jones"     to sCustomers[0][3]

    Move "Anderson"  to sCustomers[1][0]

    Move "Smith"     to sCustomers[1][1]

    Move "Verne"     to sCustomers[1][2]

    Move "Ricci"     to sCustomers[1][3]

 

    Move (CountArray("Smith",sCustomers[0])) to iCount0

    showln "Count in first row of array: " (string(iCount0))

    Move (CountArray("Smith",sCustomers[1])) to iCount1

    showln "Count in second row of array: " (string(iCount1))

    showln "Count in full array: " (string(iCount0+iCount1))

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().