楔子
给我这个列表里面所有员工的平均薪酬。通常可能会这样写
double totalSalary = 0.0;
for (Employee *employee in employees) {
totalSalary += [employee.salary doubleValue];
}
double averageSalary = totalSalary / [employees count];
但是KVC提供了一种更加简洁的方法,那就是使用集合运算符,easy
[employees valueForKeyPath:@"@avg.salary"];
正文
KVC集合运算符允许在valueForKeyPath:
方法中使用key path符号在一个集合中执行方法。无论什么时候你在key path中看见了@,它都代表了一个特定的集合方法,其结果可以被返回或者链接,就像其他的key path一样。
集合运算符会根据其返回值的不同分为以下三种类型:
- 简单的集合运算符 返回的是
strings
,number
, 或者dates
- 对象运算符 返回的是一个数组
- 数组和集合运算符 返回的是一个数组或者集合
示例
下面为一个Prduct类
@interface Product : NSObject
@property NSString *name;
@property double price;
@property NSDate *launchedOn;
@end
简单集合操作符
- @count:返回一个值为集合中对象总数的
NSNumber
对象。 - @sum:首先把集合中的每个对象都转换为
double
类型,然后计算其总,最后返回一个值为这个总和的NSNumber对象。 - @avg:首先把集合中的每个对象都转换为
double
类型,然后计算其平均值,最后返回一个值为该平均值的NSNumber对象。 - @max:使用
compare:
方法来确定最大值。所以为了让其正常工作,集合中所有的对象都必须支持和另一个对象的比较。 - @min:和@max一样,但是返回的是集合中的最小值。
代码如下
[products valueForKeyPath:@"@count"]; // 4
[products valueForKeyPath:@"@sum.price"]; // 3526.00
[products valueForKeyPath:@"@avg.price"]; // 881.50
[products valueForKeyPath:@"@max.price"]; // 1699.00
[products valueForKeyPath:@"@min.launchedOn"]; // June 11, 2012
对象操作符
现在有一个数组
NSArray *inventory = @[iPhone5, iPhone5, iPhone5, iPadMini, macBookPro, macBookPro];
@unionOfObjects/ @distinctUnionOfObjects: 返回一个由操作符右边的key path所指定的对象属性组成的数组。其中@distinctUnionOfObjects会对数组去重, 而@unionOfObjects不会。
[inventory valueForKeyPath:@"@unionOfObjects.name"]; // "iPhone 5", "iPhone 5", "iPhone 5", "iPad Mini", "MacBook Pro", "MacBook Pro"
[inventory valueForKeyPath:@"@distinctUnionOfObjects.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro"
数组和集合操作符
数组和集合操作符跟对象操作符很相似,只不过它是在NSArray和NSSet所组成的集合中工作的。如果我们做一些例如:比较几个商店中的库存(和我们上一节类似的appleStore库存和买iPhone 5和iPad Mini的versizonStore库存)这样的工作,这个就会很有用。
- @distinctUnionOfArrays/@unionOfArrays: 返回了一个数组,其中包含这个集合中每个数组对于这个操作符右面指定的key path进行操作之后的值。正如你期望的,distinct版本会移除重复的值。
- @distinctUnionOfSets:和@distinctUnionOfArrays差不多, 但是它期望的是一个包含着NSSet对象的NSSet,并且会返回一个NSSet对象。因为集合不能包含重复的值,所以它只有distinct操作。
[@[appleStoreInventory, verizonStoreInventory] valueForKeyPath:@"@distinctUnionOfArrays.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro"
写在后面
目前还不能自定义集合操作符。
参考文章:
苹果官方文档Key-Value Coding Programming Guide
KVC Collection Operators