使用集合运算符
当您向valueForKeyPath:
消息发送符合键值编码的对象时,可以在关键路径中嵌入集合运算符。集合运算符是一个小的关键字列表之一,前面是一个at符号(@
),它指定了getter应该执行的操作,以便在返回之前以某种方式操作数据。valueForKeyPath:
通过NSObject
实现此行为提供的默认实现。
当密钥路径包含集合运算符时,运算符之前的密钥路径的任何部分(称为左键路径)指示相对于消息接收者操作的集合。如果将消息直接发送到集合对象(例如NSArray
实例),则可以省略左键路径。
操作符之后的键路径部分(称为右键路径)指定操作员应处理的集合中的属性。除了@count
需要正确的密钥路径之外,所有集合运算符。图4-1说明了操作员密钥路径格式。
集合运算符表现出三种基本类型的行为:
-
聚合运算符以某种方式合并集合的对象,并返回通常与右键路径中指定的属性的数据类型匹配的单个对象。该
@count
运营商是一个例外,它没有正确的关键路径并始终将返回一个NSNumber
实例。 -
数组运算符返回一个
NSArray
实例,该实例包含命名集合中保存的对象的某个子集。 -
嵌套操作符处理包含其他集合的集合,并根据操作符返回一个
NSArray
或NSSet
实例,它以某种方式组合嵌套集合的对象。
样本数据
以下描述包括演示如何调用每个运算符的代码片段,以及执行此操作的结果。这些依赖于BankAccount
类,在呈现列表2-1,它保存的阵列Transaction
对象。每个代表一个简单的支票簿条目,如清单4-1所示。
@interface Transaction : NSObject
@property (nonatomic) NSString* payee; // To whom
@property (nonatomic) NSNumber* amount; // How much
@property (nonatomic) NSDate* date; // When
@end
为了便于讨论,假设您的BankAccount
实例有一个使用表4-1中显示的数据填充的事务数组,并且您可以从BankAccount
对象内部进行示例调用。
|
|
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
聚合运算符
聚合运算符可以处理数组或属性集,从而生成反映集合某些方面的单个值。
@avg
指定@avg
运算符时,valueForKeyPath:
读取集合中每个元素的右键路径指定的属性,将其转换为double
(用0代替nil
值),并计算这些值的算术平均值。然后它返回存储在NSNumber
实例中的结果。
要获得表4-1中的样本数据之间的平均交易金额:
NSNumber *transactionAverage = [self.transactions valueForKeyPath:@"@avg.amount"];
格式化结果transactionAverage
为$ 456.54。
@计数
指定@count
运算符时,valueForKeyPath:
返回NSNumber
实例中集合中的对象数。右键路径(如果存在)将被忽略。
获取Transaction
对象的数量transactions
:
NSNumber *numberOfTransactions = [self.transactions valueForKeyPath:@"@count"];
值numberOfTransactions
是13。
@Max
指定@max
运算符时,valueForKeyPath:
在右键路径命名的集合条目中搜索并返回最大的一个。搜索使用该compare:
方法进行比较,该方法由许多Foundation类(例如NSNumber
类)定义。因此,右键路径指示的属性必须包含一个对此消息有意义响应的对象。搜索会忽略nil
有价值的集合条目。
要获得表4-1中列出的事务中日期值的最大值(即最新事务的日期):
NSDate *latestDate = [self.transactions valueForKeyPath:@"@max.date"];
格式化的latestDate
值是2016年7月15日。
@Min
指定@min
运算符时,valueForKeyPath:
在右键路径命名的集合条目中搜索并返回最小的一个。搜索使用该compare:
方法进行比较,该方法由许多Foundation类(例如NSNumber
类)定义。因此,右键路径指示的属性必须包含一个对此消息有意义响应的对象。搜索会忽略nil
有价值的集合条目。
要获得表4-1中列出的事务中最小的日期值(即最早的事务日期):
NSDate *earliestDate = [self.transactions valueForKeyPath:@"@min.date"];
格式化的earliestDate
值是2015年12月1日。
@和
指定@sum
运算符时,valueForKeyPath:
读取集合中每个元素的右键路径指定的属性,将其转换为double
(将0替换为nil
值),并计算这些值的总和。然后它返回存储在NSNumber
实例中的结果。
要获得表4-1中样本数据之间的事务数量总和:
NSNumber *amountSum = [self.transactions valueForKeyPath:@"@sum.amount"];
格式化结果amountSum
为$ 5,935.00。
数组运算符
数组运算符导致valueForKeyPath:
返回与右键路径指示的特定对象集相对应的对象数组。
重要
valueForKeyPath:
如果任何叶子对象nil
在使用数组运算符时,该方法会引发异常。
@distinctUnionOfObjects
指定@distinctUnionOfObjects
运算符时,valueForKeyPath:
创建并返回一个数组,该数组包含与右键路径指定的属性对应的集合的不同对象。
要获取payee
事务的属性值集合,transactions
并忽略重复值:
NSArray *distinctPayees = [self.transactions valueForKeyPath:@"@distinctUnionOfObjects.payee"];
结果distinctPayees
数组包含以下每个字符串的一个实例:汽车贷款,通用电缆,动物医院,绿色电力,抵押贷款。
注意
该@unionOfObjects
运营商提供类似的行为,但没有删除重复的对象。
@unionOfObjects
指定@unionOfObjects
运算符时,valueForKeyPath:
创建并返回一个数组,该数组包含与右键路径指定的属性对应的集合的所有对象。与@distinctUnionOfObjects不同,不会删除重复的对象。
要获取payee
以下事务中的事务的属性值集合transactions
:
NSArray *payees = [self.transactions valueForKeyPath:@"@unionOfObjects.payee"];
结果payees
阵列包含以下字符串:绿色电力,绿色电力,绿色电力,汽车贷款,汽车贷款,汽车贷款,通用电缆,通用电缆,通用电缆,抵押贷款,抵押贷款,抵押贷款,动物医院。请注意重复项。
注意
该@distinctUnionOfArrays
运营商类似,但删除重复的对象。
嵌套运营商
嵌套运算符对嵌套集合进行操作,集合中的每个条目都包含一个集合。
重要
valueForKeyPath:
如果任何叶对象nil
在使用嵌套运算符时,该方法会引发异常。
对于下面的描述,考虑第二个数据数组moreTransactions
,使用表4-2中的数据填充,并与原始transactions
数组(从“ 示例数据”部分)一起收集到嵌套数组中:
NSArray* moreTransactions = @[<# transaction data #>];
NSArray* arrayOfArrays = @[self.transactions, moreTransactions];
|
|
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@distinctUnionOfArrays
指定@distinctUnionOfArrays
运算符时,valueForKeyPath:
创建并返回一个数组,该数组包含与右键路径指定的属性对应的所有集合的组合的不同对象。
要payee
在以下所有数组中获取属性的不同值arrayOfArrays
:
NSArray *collectedDistinctPayees = [arrayOfArrays valueForKeyPath:@"@distinctUnionOfArrays.payee"];
结果collectedDistinctPayees
数组包含以下值:业余爱好商店,抵押贷款,动物医院,二等抵押贷款,汽车贷款,通用电缆 - 小屋,通用电缆,绿色电力。
注意
该@unionOfArrays
操作是类似的,但不删除重复的对象。
@unionOfArrays
指定@unionOfArrays
运算符时,valueForKeyPath:
创建并返回一个数组,该数组包含与右键路径指定的属性对应的所有集合的组合的所有对象,而不删除重复项。
要获取以下payee
所有数组中的属性值arrayOfArrays
:
NSArray *collectedPayees = [arrayOfArrays valueForKeyPath:@"@unionOfArrays.payee"];
结果 collectedPayees
数组包含以下值:绿色电力,绿色电力,绿色电力,汽车贷款,汽车贷款,汽车贷款,通用电缆,通用电缆,通用电缆,抵押贷款,按揭贷款,按揭贷款,动物医院,通用电缆 - 小屋,一般电缆 - 小屋,通用电缆 - 小屋,第二按揭,第二按揭,第二按揭,业余爱好商店。
注意
该@distinctUnionOfArrays
运营商类似,但删除重复的对象。
@distinctUnionOfSets
指定@distinctUnionOfSets
运算符时,valueForKeyPath:
创建并返回一个NSSet
对象,该对象包含与右键路径指定的属性对应的所有集合的组合的不同对象。
此运算符的行为与此类似@distinctUnionOfArrays
,只是它需要一个NSSet
包含NSSet
对象实例而不是NSArray
实例实例的NSArray
实例。此外,它返回一个NSSet
实例。假设示例数据已存储在集合而不是数组中,示例调用和结果与显示的相同@distinctUnionOfArrays
。