Skip to content

Changes in Struct and Array Functions

BinarySearchInsertPos

BinarySearchInsertPos()

This function was created to provide a way to insert an item into a sorted array while maintaining the proper sort order.

If a binary search applied to a sorted array fails to find the target, it returns -1.

Move (BinarySearchArray(Target, MySortedArray)) to iIndex // if -1, not found
Move (BinarySearchArray(Target, MySortedArray, hoObject, hMsg)) to iIndex // if -1, not found

This only tells you that the item was not found. If you immediately call BinarySearchInsertPos following that failed search, it will return the position in the array where the missing item should have been found, which is the position where it should be inserted. You can use this value with InsertInArray to add the missing item to the array. This provides a mechanism for adding items to an already sorted array without needing to resort the entire array.

Move (BinarySearchArray(Target, MySortedArray)) to iIndex // if -1, not found
If (iIndex = -1) Begin
    Move (BinarySearchInsertPos()) to iIndex
    Move (InsertInArray(MySortedArray, iIndex, Target)) to MySortedArray
End

As with any binary search operation, it is the developer's responsibility to ensure that the array is properly sorted. The developer must also ensure that BinarySearchInsertPos is called before any other array search is performed.

Inserting an item into a very long array has a performance penalty as the array has to be shifted to make room for a new item. Appending values to an array is always the fastest way to add an item. Sorting an array also has an overhead, but often this occurs only once after all items are added. With very large arrays, inserting a limited number of items into their sorted position may be faster than appending the items and then sorting them.

IsSameArray

IsSameArray(Array1, Array2)

Returns true if the two arrays are the same. They are the same if they are of the same type, have the same number of dimensions, the same dimension size, and the same content.

IsSameStruct

IsSameStruct(Struct1, Struct2)

Returns true if the two structs are the same. They are the same if they are of the same struct type with the same content.

InsertInArray

If -1 is passed as the index, the item will be "inserted" at the end of the array, making it an append. You can also pass the size of the array as your index, which will append the item at the end.

RemoveFromArray

If -1 is passed as the index, the item will be removed from the end of the array.

Searching and Sorting Struct Arrays Change

The functions SortArray(), SearchArray(), BinarySearchArray(), CountArray(), MaxArray(), and MinArray() all support two calling styles. One passes a custom object and custom method for comparing values while the other expects the runtime to make these comparisons internally. For example:

// Simple style
Move (SearchArray(MySearchValue, MyArray)) to iIndex

// Extended style
Move (SearchArray(MySearchValue, MyArray, oMySearchObject, RefFunc(MySearchFn))) to iIndex

The simple style lets the runtime do all the work, while the expanded style requires that you create a function to do the comparison. The expanded style allows for custom comparisons and provides a way to compare complex data (e.g., arrays of structs) where it is not clear what the sorted order should be. It requires more programming and is slower than a runtime comparison.

Previously, arrays of structs had to use the expanded style. You can now use the simpler style with structs. If the short style of the function is used, 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 datatype (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.

This applies to the global array functions SortArray(), SearchArray(), BinarySearchArray(), CountArray(), MaxArray(), and MinArray().

This makes it easy to create paired sets (or dictionaries) where the first member is a key and the second member (and all other members) contain data. You search and sort via the key.

For example:

Struct tMyData
    String sID // Assume some unique ID
    String sLastName
    String sFirstName
    RowId riRowId
End_Struct

tCustomerData[] CustArray
tCustomerData SearchCust // This will be our search struct

Send LoadAllCustomers to CustArray

// Will sort on first member, sID order
Move (SortArray(CustArray)) to CustArray

// Will search on first member, sID
Move "xyz" to SearchCust.sID
Move (BinarySearchArray(SearchCust, CustArray)) to iIndex

// If key not found, add it
If (iIndex = -1) Begin
    Move (BinarySearchInsertPos()) to iIndex
    Move (InsertInArray(CustArray, iIndex, SearchCust)) to CustArray
End

You could also use this at a more abstract level where the first member is always the key and the second member is always your data.

Struct tMyDataPair
    String sKey
    tSomeCustomStruct SomeData
End_Struct

An even more generic version of this would make the second member a variant, so it can be used for any type of data (simple, structs, or arrays). In such a case, the developer must know what the data type is and move it to an appropriate DataFlex variable when working with it.

Struct tDataPair
    String sKey
    Variant vData
End_Struct

When using automatic first member struct searching/sorting, the first data member must be a simple DataFlex type (String, Integer, etc.). If not, a runtime error is raised. This "first member" smart comparison will not be appropriate for all comparisons. When it is not, you should continue to use the extended function format, whose usage is unchanged.

Sorting and Searching via RowId

You can now 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 that it can allow faster searching when used with BinarySearchArray().

See Also

What's New in DataFlex 2015 - 18.1