Collection Operators

Collection operators allow actions to be performed on the items of a collection using key path notation and an action operator. This article describes the available collection operators, example key paths, and the results they’d produce.

Collection operators are specialized key paths that are passed as the parameter to the valueForKeyPath: method. The operator is specified by a string preceded by an at sign (@). The key path on the left side of the collection operator, if present, determines the array or set, relative to the receiver, that is used in the operation. The key path on the right side of the operator specifies the property of the collection that the operator uses. Figure 1 illustrates the operator key path format.

Figure 1  Operator key path format

All the collection operators, with the exception of @count, require a key path to the right of the collection operator.

The type of object value returned depends on the operator:

Data Used In Examples

Each of the operators in “Simple Collection Operators,” “Object Operators,” and “Array and Set Operators” includes an example code snippet using a key path containing an operator, as well as the results that would be generated. To illustrate this it is necessary to use a theoretical class, in this case the Transaction class. The Transaction class encapsulates the simplest form of checkbook entires. It contains three properties: payee (an NSString), amount (an NSNumber), and date (an NSDate).

The Transaction instances are stored in a collection object that is assigned to the hypothetical variable transactions, which is an instance of NSArray. For the operator that operates on an NSSet collection, it can be assumed that the transactions collection is an instance of NSSet. This is discussed in the relevant operators.

In order to provide results data for the operator action on the transactions collection sample data is required. Each row in Table 1 contains the data for an instance of Transaction. The values in the table have been formatted (where applicable) to make them easier to understand. The results displayed by the examples are also formatted.

Table 1  Example data for the Transactions objects

payee values

amount values (formatted as currency)

date values (formatted as month day, year)

Green Power

$120.00

Dec 1, 2009

Green Power

$150.00

Jan 1, 2010

Green Power

$170.00

Feb 1, 2010

Car Loan

$250.00

Jan 15, 2010

Car Loan

$250.00

Feb 15, 2010

Car Loan

$250.00

Mar 15, 2010

General Cable

$120.00

Dec 1, 2009

General Cable

$155.00

Jan 1, 2010

General Cable

$120.00

Feb 1, 2010

Mortgage

$1,250.00

Jan 15, 2010

Mortgage

$1,250.00

Feb 15, 2010

Mortgage

$1,250.00

Mar 15, 2010

Animal Hospital

$600.00

Jul 15, 2010

Simple Collection Operators

Simple collection operators operate on the properties to the right of the operator in either an array or set.

@avg

The @avg operator uses valueForKeyPath: to get the values specified by the property specified by the key path to the right of the operator, converts each to a double, and returns the average value as an instance of NSNumber. In the case where the value is nil, 0 is assumed instead.

The following example returns the average value of the transaction amount for the objects in transactions:

NSNumber *transactionAverage = [transactions valueForKeyPath:@"@avg.amount"];

The formatted result of transactionAverage is $456.54.

@count

The @count operator returns the number of objects in the left key path collection as an instance of NSNumber, the key path to the right of the operator is ignored.

The following example returns the number of Transaction objects in transactions:

NSNumber *numberOfTransactions = [transactions valueForKeyPath:@"@count"];

The value of numberOfTransactions is 13.

@max

The @max operator compares the values of the property specified by the key path to the right of the operator and returns the maximum value found. The maximum value is determined using the compare: method of the objects at the specified key path. The compared property objects must support comparison with each other. If the value of the right side of the key path is nil, it is ignored.

The following example returns the maximum value of the date values (date of the latest transaction) for the Transaction objects in transactions:

NSDate *latestDate = [transactions valueForKeyPath:@"@max.date"];

The latestDate value (formatted) is Jul 15, 2010.

@min

The @min operator compares the values of the property specified by the key path to the right of the operator and returns the minimum value found. The minimum value is determined using the compare: method of the objects at the specified key path. The compared property objects must support comparison with each other. If the value of the right side of the key path is nil, it is ignored.

The following example returns the minimum value (date of the earliest transaction) of the date property for the Transaction objects in transactions:

NSDate *earliestDate = [transactions valueForKeyPath:@"@min.date"];

The earliestDate value (formatted) is Dec 1, 2009.

@sum

The @sum operator returns the sum of the values of the property specified by the key path to the right of the operator. Each number is converted to a double, the sum of the values is computed, and the total is wrapped as an instance of NSNumber and returned. If the value of the right side of the key path is nil, it is ignored.

The following example returns the sum of the amounts property for the transactions in transactions:

NSNumber *amountSum = [transactions valueForKeyPath:@"@sum.amount"];

The resulting amountSum value (formatted) is $5,935.00.

Object Operators

The object operators provide results when they are applied to a single collection instance.

@distinctUnionOfObjects

The @distinctUnionOfObjects operator returns an array containing the distinct objects in the property specified by the key path to the right of the operator.

The following example returns the payee property values for the transactions in transactions with any duplicate values removed:

NSArray *payees = [transactions valueForKeyPath:@"@distinctUnionOfObjects.payee"];

The resulting payees array contains the following strings: Car Loan, General Cable, Animal Hospital, Green Power, Mortgage.

The @unionOfObjects operator is similar, but does not remove duplicate objects.

@unionOfObjects

The @unionOfObjects operator returns an array containing the distinct objects in the property specified by the key path to the right of the operator. Unlike “@distinctUnionOfObjects,” duplicate objects are not removed.

The following example returns the payee property values for the transactions in transactions:

NSArray *payees = [transactions valueForKeyPath:@"@unionOfObjects.payee"];

The resulting payees array contains the following strings: Green Power, Green Power, Green Power, Car Loan, Car Loan, Car Loan, General Cable, General Cable, General Cable, Mortgage, Mortgage, Mortgage, Animal Hospital.

The @distinctUnionOfArrays operator is similar, but removes duplicate objects.

Array and Set Operators

The array and set operators operate on nested collections, that is, a collection where each entry contains a collection.

The variable arrayOfTransactions is used in the example for each operator. It is an array containing two arrays of Transaction objects.

The following code snippet shows how the nested collection would be created:

// Create the array that contains additional arrays.
self.arrayOfTransactionsArray = [NSMutableArray array];
 
// Add the array of objects used in the above examples.
[arrayOfTransactionsArray addObject:transactions];
 
// Add a second array of objects; this array contains alternate values.
[arrayOfTransactionsArrays addObject:moreTransactions];

The first array of Transaction objects contains the data listed in Table 1 and the second array (moreTransactions) contains Transaction objects with the hypothetical data in Table 2.

Table 2  Hypothetical Transaction data in the moreTransactions array

payee values

amount values (formatted as currency)

date values (formatted as month day, year)

General Cable - Cottage

$120.00

Dec 18, 2009

General Cable - Cottage

$155.00

Jan 9, 2010

General Cable - Cottage

$120.00

Dec 1, 2010

Second Mortgage

$1,250.00

Nov 15, 2010

Second Mortgage

$1,250.00

Sep 20, 2010

Second Mortgage

$1,250.00

Feb 12, 2010

Hobby Shop

$600.00

Jun 14, 2010

@distinctUnionOfArrays

The @distinctUnionOfArrays operator returns an array containing the distinct objects in the property specified by the key path to the right of the operator.

The following code example will return the distinct values of the payee property in all the arrays with arrayOfTransactionsArrays:

NSArray *payees = [arrayOfTransactionsArrays valueForKeyPath:@"@distinctUnionOfArrays.payee"];

The resulting payees array contains the following values: Hobby Shop, Mortgage, Animal Hospital, Second Mortgage, Car Loan, General Cable - Cottage, General Cable, Green Power.

The @unionOfArrays operator is similar, but does not remove duplicate objects.

@unionOfArrays

The @unionOfArrays operator returns an array containing the objects in the property specified by the key path to the right of the operator. Unlike @distinctUnionOfArrays, duplicate objects are not removed.

The following code example will return the values of the payee property in all the arrays with arrayOfTransactionsArrays:

NSArray *payees = [arrayOfTransactionsArrays valueForKeyPath:@"@unionOfArrays.payee"];

The resulting payees array contains the following values: Green Power, Green Power, Green Power, Car Loan, Car Loan, Car Loan, General Cable, General Cable, General Cable, Mortgage, Mortgage, Mortgage, Animal Hospital, General Cable - Cottage, General Cable - Cottage, General Cable - Cottage, Second Mortgage, Second Mortgage, Second Mortgage, Hobby Shop.

@distinctUnionOfSets

The @distinctUnionOfSets operator returns a set containing the distinct objects in the property specified by the key path to the right of the operator.

This operator works the same as @distinctUnionOfArrays, except that it expects an NSSet instance containing NSSet instances of Transaction objects rather than arrays. It returns an NSSet instance. Using the example data set, the returned set would contain the results as those shown in “@distinctUnionOfArrays.”