Applies To:
  • CitectSCADA v5.x, v6.x, v7.x 

Summary:
How can you efficiently search an array to find the location of a certain item in it?

Solution:

The TableLookup() Cicode function can be used to search an array. Unfortunately, it only works for arrays of REAL (floating point) values. For INT or STRING arrays, custom Cicode will be needed. The simplest method is to use a FOR loop to check each element in the array and compare it with the desired value. This can be done with the linear search code below:

//Searches gsSortArray for the sFind text and returns its element 
//number (between nFirst and nLast) or -1 if it was not found
INT
FUNCTION
LinearSearch(STRING sFind, INT nFirst = 0, INT nLast = 478)
INT nItem;

FOR nItem = nFirst TO nLast DO
IF sFind = gsSortArray[nItem] THEN
RETURN nItem;
END
END

RETURN -1;
END

If the list is sorted (in alphabetical or numeric order--see Q3750), it is much faster to use the binary search method. This algorithm looks at the middle item in the list. If it is greater than the item to find, the search is repeated on the first half of the list, otherwise the 2nd half of the list is checked. Each time the list is cut in half until only the desired item remains (or no item remains if the search item doesn't exist). With a linear search of 100 items, on average half of the items will be checked before a match is found and all items must be checked if there is no match. With a binary search of 100 items only 6 or 7 items will need to be checked.

Since binary search requires that the list is sorted, it may not be the best choice if the list is constantly changing. Having to re-sort the list each time will cancel out the benefit of Binary Search.

Although this binary search function is for strings, it can be used for numbers simply by changing the STRING variables to REAL or INT.

GLOBAL STRING	gsSortArray[479]; 	//Contains sorted list of strings to search 
// Search an ordered array for the first occurrence of the specified element 
// using the binary search algorithm. The element must match sFind exactly
// to be successful (but case is ignored)
//
// Arguments: sFind Text to find
// nFirst First element to search (normally 0)
// nLast Last element to search (max 478 for strings)
//
// Returns the element number if successful, or -1 if the element was not found
//
// Note: 1. All elements in gsSortArray must be in alphabetical order
// 2. If nFirst or nLast are outside of the array's bounds, a hardware
// alarm is generated
// 3. If the array has any blank elements, they must be before nFirst or
// after nLast
//
INT
FUNCTION
BinarySearch(STRING sFind, INT nFirst = 0, INT nLast = 478)
INT nMiddle, nHigh = nLast + 1, nLow = nFirst - 1;
	WHILE (nHigh - nLow) > 1 DO
nMiddle = nLow + ((nHigh - nLow) / 2);
IF gsSortArray[nMiddle] < sFind THEN
nLow = nMiddle;
ELSE
nHigh = nMiddle;
END
END
	IF (nHigh = nLast + 1) THEN
RETURN -1;
ELSE
IF (gsSortArray[nHigh] <> sFind) THEN
RETURN -1;
ELSE
RETURN nHigh;
END
END
END
 

Keywords:
 

Attachments