当你对一个对象(集合/数组)发送了valueForKeyPath:
消息的时候,集合操作允许你通过嵌入关键字的形式作出相应的操作. 集合操作符是一个以@
开头的特殊字符串. for example: @distinctUnionOfObjects.self
无论什么时候你在key path中看见了@
,它都代表了一个特定的集合方法,其结果可以被返回或者链接.
开始前,我们先定义一个产品模型ProductModel
并准备好数据:
@interface ProductModel : NSObject
@property (nonatomic, strong) NSString *name;//产品名称
@property (nonatomic, assign) CGFloat price;//产品价格
@end
//模拟数据
ProductModel *productA = [[ProductModel alloc] init];
productA.price = 99.0;
productA.name = @"iPod";
ProductModel *productB = [[ProductModel alloc] init];
productB.price = 199.0;
productB.name = @"iMac";
ProductModel *productC = [[ProductModel alloc] init];
productC.price = 299.0;
productC.name = @"iPhone";
ProductModel *productD = [[ProductModel alloc] init];
productD.price = 199.0;
productD.name = @"iPhone";
KVC 集合操作符类型
- Simple Collection Operators 简单的集合操作符
- Object Operators 对象操作符
- Array and Set Operators 数组/集合操作符
简单的集合操作
@count
返回一个值为集合中对象总数的 NSNumber 对象@avg
首先把集合中的对象都转换成 double 类型,然后计算其平均值,并返回这个平均值的 NSNumber 对象@max
使用compare:
方法来确定最大值,并返回最大值的 NSNumber 对象,所以为了保证其正常的比较,集合中的所有对象必须支持和另一个对象的比较,保证其可比性.@min
原理和@max
一样,返回集合中最小值的 NSNumber 对象@sum
首先把集合中的对象都转换成 double 类型,然后计算其总和,并返回这个总和的 NSNumber 对象
NOtice:所有的集合操作,除了@ count
外,其他的都需要有右边的 keypath
(一般为属性名),@count
右边的 keypath
可写可不写
NSArray *product = @[productA, productB, productC, productD];
NSNumber *count = [product valueForKeyPath:@"@count.price"];
NSNumber *avg = [product valueForKeyPath:@"@avg.price"];
NSNumber *max = [product valueForKeyPath:@"@max.price"];
NSNumber *min = [product valueForKeyPath:@"@min.price"];
NSNumber *sum = [product valueForKeyPath:@"@sum.price"];
NSLog(@"count:%@, avg:%@, max:%@, min:%@, sum:%@", count, avg, max, min, sum); // count:4, avg:199, max:299, min:99, sum:796
Notice:若操作对象(数组/集合)内的元素本身就是 NSNumber 对象,那么可以这样写.
NSArray *array = @[@(productA.price), @(productB.price), @(productC.price), @(productD.price)];
NSNumber *count = [array valueForKeyPath:@"@count"];
NSNumber *avg = [array valueForKeyPath:@"@avg.self"];
NSNumber *max = [array valueForKeyPath:@"@max.self"];
NSNumber *min = [array valueForKeyPath:@"@min.self"];
NSNumber *sum = [array valueForKeyPath:@"@sum.self"];
NSLog(@"count:%@, avg:%@, max:%@, min:%@, sum:%@", count, avg, max, min, sum);//count:4, avg:199, max:299, min:99, sum:796
对象操作符
unionOfObjects:
获取数组中每个对象的属性的值,放在一个数组中并返回,但不会去重distinctUnionOfObjects:
获取数组中每个对象的属性的值,放在一个数组中并返回,会对数组去重;常用来对数组元素去重,快捷高效
NSArray *unionOfObjects = [product valueForKeyPath:@"@unionOfObjects.name"];
NSArray *distinctUnionOfObjects = [product valueForKeyPath:@"@distinctUnionOfObjects.name"];
NSLog(@"unionOfObjects : %@", unionOfObjects);//iPod,iMac,iPhone,iPhone
NSLog(@"distinctUnionOfObjects : %@", distinctUnionOfObjects);//iPhone,iPod,iMac
数组/集合操作符(可粗略理解为二维数组/集合的展开
)
@distinctUnionOfArrays
返回操作对象(且操作对象必须是数组/集合)中的所有元素,即返回这个数组本身,会去重unionOfArrays
首先获取操作对象(且操作对象必须是数组/集合)中的所有元素,然后装到一个新的数组中并返回,不会对这个数组去重
Notice: 操作对象中的元素必须是数组
NSArray *distinctUnionOfArrays = [@[product, product] valueForKeyPath:@"@distinctUnionOfArrays.price"];
NSArray *unionOfArrays = [@[product, product] valueForKeyPath:@"@unionOfArrays.price"];
NSLog(@"distinctUnionOfArrays : %@", distinctUnionOfArrays);//299,99,199
NSLog(@"unionOfArrays : %@", unionOfArrays);//99,199,299,199,99,199,299,199
distinctUnionOfSets
返回操作对象(且操作对象必须是数组/集合)中数组/集合的所有对象,返回值为集合,因为集合不能包含重复值,所以它只能有 distinct操作 Notice: 操作对象中的元素必须是集合
NSSet *setA = [NSSet setWithObjects:productA, productB, nil];
NSSet *setB = [NSSet setWithObjects:productC, productD, nil];
NSSet *set = [NSSet setWithObjects:setA, setB, nil];
NSSet *allSet = [set valueForKeyPath:@"@distinctUnionOfSets.name"];
NSLog(@"distinctUnionOfSets: %@", allSet);//iPhone,iPod,iMac
具体的应用举例
删除重复值
NSArray *array = @[@"name", @"w", @"aa", @"zxp", @"aa"];
//返回的是一个新的数组
NSArray *newArray = [array valueForKeyPath:@"@distinctUnionOfObjects.self"];
NSLog(@"%@", newArray);
同样可以嵌套使用,先剔除name对应值的重复数据再取值
NSArray *array = @[
@{@"title":@"zxp",@"name":@"zhangxiaoping"},
@{@"title":@"zxp2",@"name":@"zhangxiaoping2"},
@{@"title":@"zxp",@"name":@"zhangxiaoping3"},
@{@"title":@"zxp",@"name":@"zhangxiaoping"}];
//根据name字段,来进行重复删除。
NSArray *newArray = [array valueForKeyPath:@"@distinctUnionOfObjects.name"];//如果要根据title字段来删除重名的写法为`@distinctUnionOfObjects.title`
NSLog(@"%@", newArray);
/*print:
(
zhangxiaoping3,
zhangxiaoping2,
zhangxiaoping
)
是一个字符串数组
*/
获取数组里的,最大、最小、平均、求和
NSArray *array = @[@1, @2, @3, @4, @10];
NSNumber *sum = [array valueForKeyPath:@"@sum.self"];
NSNumber *avg = [array valueForKeyPath:@"@avg.self"];
NSNumber *max = [array valueForKeyPath:@"@max.self"];
NSNumber *min = [array valueForKeyPath:@"@min.self"];
或者指定输出类型
NSNumber *sum = [array valueForKeyPath:@"@sum.floatValue"];
NSNumber *avg = [array valueForKeyPath:@"@avg.floatValue"];
NSNumber *max = [array valueForKeyPath:@"@max.floatValue"];
NSNumber *min = [array valueForKeyPath:@"@min.floatValue"];
NSDictionary 获取相应的 key
NSArray *array = @[@{@"name" : @"cookeee",@"code" : @1},
@{@"name": @"jim",@"code" : @2},
@{@"name": @"jim",@"code" : @1},
@{@"name": @"jbos",@"code" : @1}];
NSLog(@"%@", [array valueForKeyPath:@"name"]);
进行实例方法的调用
NSArray *array = @[@"name", @"w", @"aa", @"ZXPing"];
NSLog(@"%@", [array valueForKeyPath:@"uppercaseString"]);
改变 UITextfield 的 placeholder 的颜色
[searchField setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];
比起重写- (void)drawPlaceholderInRect:(CGRect)rect;要方便很多
我怎样才能最容易地展平一个三维数组
NSArray *threeDimensionalArray = @[
@[
@[ @"Peter", @"Paul", @"Mary" ], @[ @"Joe", @"Jane" ]
],
@[
@[ @"Alice", @"Bob" ]
]
];
//我希望得到
@[ @"Peter", @"Paul", @"Mary", @"Joe", @"Jane", @"Alice", @"Bob" ]
键值编码(KVC)集合运算符@unionOfArrays展平一个级别的数组,因此将其应用两次会产生所需的结果。
集合运算符(@count除外)需要一个集合属性的关键路径,由于我们的对象本身已经是数组(因此集合),关键路径必须是self。
因此,我们需要与self关键路径应用@unionOfArrays两次,得到以下KVC调用展平三维数组:
NSArray *flattenedArray = [threeDimensionalArray valueForKeyPath: @"@unionOfArrays.self.@unionOfArrays.self"];
获得 NSDictionary NSArray 的值列表
我有以下 NSArray:
NSArray myArray = @[@{@300:@"5 min"},
@{@900:@"15 min"},
@{@1800:@"30 min"},
@{@3600:@"1 hour"}];
我想我的字典的值的列表︰@[@"5 min",@"15 min",@"30 min",@"1 hour"]
和我的字典的键的列表︰@[@300, @900, @1800, @3600]
NSArray *values = [myArray valueForKeyPath: @"@unionOfArrays.@allValues"];
NSArray *keys = [myArray valueForKeyPath: @"@unionOfArrays.@allKeys"];
一个简短的解释可能是顺序︰
我们想要的结果是
所有的值 (或键) 的每个词典,获取数组的数组的值 (或键)
然后我们要拼合到单个阵列中的这些阵列。
要获得使用 KVC 词典的所有值 (或键),特殊键是 @allValues 或 @allKeys ,分别。
@unionOfArrays阵列联盟获得从它,即,后面的表达式的运算符使展平它到你想要的数组。