對數(shù)組進(jìn)行過濾
// 返回值是原數(shù)組
[mutableArray filterUsingPredicate:/*NSPredicate*/];
// 返回新的數(shù)組
[mutableArray filteredArrayUsingPredicate:/*NSPredicate*/];
初始化
雖然 predicate 可以從 NSExpression、NSCompoundPredicate 或 NSComparsionPredicate 中實例化,但它還可以用一個字符串的語法生成。這和可視化格式語言類似,我們可以用它定義排版約束。
// USERIDS 是一個包含 userId 的集合
// 查詢 employees <People集合> 中的 identifier 在 USERIDS的
NSPredicate *morningAttendees = [NSPredicate predicateWithFormat:@"SELF.identifier IN %@", USERIDS];
NSArray *peopleAttendingMorningEvent = [employees filteredArrayUsingPredicate:morningAttendees];
NSPredicate 引入了 keypath來做匹配
[NSPredicate predicateWithFormat:@"SELF.%K IN %@", @"identifier", peopleAttendingMorningEvent];
假設(shè)我們還需要像上面一樣找到所有參加活動的人,但還要滿足他們的工資水平在 50000 到 60000 之間。
[NSPredicate predicateWithFormat:@"SELF.identifier IN %@ && SELF.paygrade.integerValue BETWEEN {50000, 60000}", peopleAttendingMorningEvent];
為了提高可讀性,符號和字符是都支持的
&& 或 AND
|| 或 OR
! 或 NOT
比較
CONTAINS 包含 x
BEGINSWITH 以 x 開始
ENDSWITH 以 x 結(jié)束
LIKE 模糊匹配
// 查詢 self.name 是以 `K`開頭的
[NSPredicate predicateWithFormat:@"SELF.name BEGINSWITH 'K'"];
// 查詢是以 Kar* 來模糊匹配的
[NSPredicate predicateWithFormat:@"SELF.name LIKE 'Kar*'"];
// 復(fù)合查詢
NSString *predicateFormat = @"(SELF.name LIKE 'Kar*') AND (SELF.paygrade.intValue >= 10)";
NSPredicate *namesStringWithK = [NSPredicate predicateWithFormat:predicateFormat];
同樣的也支持 正則表達(dá)式
// phoneNumberRegex 手機(jī)號正則
[NSPredicate predicateWithFormat:@"SELF.phoneNumber MATCHES %@", phoneNumberRegex];
為了安全可以結(jié)合 NSStringFromSelector一起使用
NSString *predicateFormat = @"(SELF.%@ LIKE 'Kar*') AND (SELF.paygrade.intValue >= 10)"
NSString *kpName = NSStringFromSelector(@selector(identifier));
NSString *kpPaygrade = NSStringFromSelector(@selector(paygrade));
NSPredicate *namesStartingWithK = [NSPredicate predicateWithFormat:predicateFormat, kpName, kpPaygrade];
// 現(xiàn)在只有 Karl 了
[mutablePersonAr filterUsingPredicate:namesStartingWithK];
KeyPath 集合查詢
// 假設(shè)一個 Person 對象現(xiàn)在有一個下面的屬性:
// NSArray *previousPay
// 找到所有滿足過去工資的平均值大于 10 的人
NSString *predicateFormat = @"SELF.previousPay.@avg.doubleValue > 10";
NSPredicate *previousPayOverTen = [NSPredicate predicateWithFormat:predicateFormat];
// 所有過去工資的平均值大于 10 的人
[mutablePersonAr filterUsingPredicate:previousPayOverTen];
@avg 均值
@sum 求和
@max 最大值
@min 最小值
@count 數(shù)量
數(shù)組的深入探討
array[FIRST] array[LAST] array[SIZE] array[index]
// 找到所有過去有三份不同工資的人
NSString *predicateFormat = @"previousPay[SIZE] == 3";
NSPredicate *threePreviousSalaries = [NSPredicate predicateWithFormat:predicateFormat];
// 這些 Person 對象過去有三份不同的工資
[mutablePersonAr filterUsingPredicate:threePreviousSalaries];
// 找到所有過去有三個不同的工資以及第一份工資大于 8 的人
NSString *predicateFormat = @"(previousPay[SIZE] == 3) AND (previousPay[FIRST].intValue > 8)";
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFormat];
[mutablePersonAr filterUsingPredicate:predicate];
更復(fù)雜的情況
@distinctUnionOfArrays
@unionOfArrays
@unionOfObjects
@distinctUnionOfObjects
// 假設(shè) p1/2/3/4 都是 Person 對象
NSArray <P*> *previousEmployees = @[@[p1],@[p2,p1,p2],@[p1],@[p4,p2],@[p4],@[p4],@[p1]];
// 獲取所有不同的 ID
NSArray *unqiuePreviousEmployeeIDs = [previousEmployees valueForKeyPath:@"@distinctUnionOfObjects.identifier"];
// 現(xiàn)在數(shù)組里應(yīng)該只含有不同的 ID
子查詢
// 假設(shè) Person 對象有了一個新的屬性表示他們的隊伍:
// NSArray *team;
// 從雇員數(shù)組中找出這樣的人,他們的團(tuán)隊中有人滿足這個條件:沒有歷史工資數(shù)據(jù)并且工資大于 1
NSString *predicateFormat = @"SUBQUERY(team, $teamMember, $teamMember.paygrade.intValue > 1 AND $teamMember.previousPay == nil).@count > 0";
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFormat];
[employeeAr filterUsingPredicate:predicate];