轉(zhuǎn)載自:http://www.cocoachina.com/ios/20160111/14926.html
1贴届、大小判斷
>=伦连,=>:判斷左邊表達(dá)式的值是否大于或等于右邊表達(dá)式的值
<=笔横,=<:判斷右邊表達(dá)式的值是否小于或等于右邊表達(dá)式的值
>:判斷左邊表達(dá)式的值是否大于右邊表達(dá)式的值
<:判斷左邊表達(dá)式的值是否小于右邊表達(dá)式的值
!=厂镇、<>:判斷兩個(gè)表達(dá)式是否不相等
BETWEEN:BETWEEN表達(dá)式必須滿足表達(dá)式 BETWEEN {下限苍糠,上限}的格式涮较,要求該表達(dá)式必須大于或等于下限稠鼻,并小于或等于上限
NSNumber *testNumber = @123;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN {100, 200}"];
if ([predicate evaluateWithObject:testNumber]) {
NSLog(@"testString:%@", testNumber);
} else {
NSLog(@"不符合條件");
}
2.邏輯運(yùn)算符
AND、&&:邏輯與狂票,要求兩個(gè)表達(dá)式的值都為YES時(shí)候齿,結(jié)果才為YES。
NSArray *testArray = @[@1, @2, @3, @4, @5, @6];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];
NSArray *filterArray = [testArray filteredArrayUsingPredicate:predicate];
NSLog(@"filterArray:%@", filterArray);
輸出結(jié)果為:
2016-01-07 11:27:01.885 PredicteDemo[4531:89537] filterArray:(
3,
4
)
OR闺属、||:邏輯或慌盯,要求其中一個(gè)表達(dá)式為YES時(shí),結(jié)果就是YES
NOT掂器、 !:邏輯非润匙,對原有的表達(dá)式取反
3.字符串比較運(yùn)算符
BEGINSWITH:檢查某個(gè)字符串是否以指定的字符串開頭(如判斷字符串是否以a開頭:BEGINSWITH 'a')
ENDSWITH:檢查某個(gè)字符串是否以指定的字符串結(jié)尾
CONTAINS:檢查某個(gè)字符串是否包含指定的字符串
LIKE:檢查某個(gè)字符串是否匹配指定的字符串模板。其之后可以跟?代表一個(gè)字符和*代表任意多個(gè)字符兩個(gè)通配符唉匾。比如"name LIKE '*ac*'"孕讳,這表示name的值中包含ac則返回YES;"name LIKE '?ac*'"巍膘,表示name的第2厂财、3個(gè)字符為ac時(shí)返回YES。
MATCHES:檢查某個(gè)字符串是否匹配指定的正則表達(dá)式峡懈。雖然正則表達(dá)式的執(zhí)行效率是最低的璃饱,但其功能是最強(qiáng)大的,也是我們最常用的肪康。
注:字符串比較都是區(qū)分大小寫和重音符號的荚恶。如:café和cafe是不一樣的,Cafe和cafe也是不一樣的磷支。如果希望字符串比較運(yùn)算不區(qū)分大小寫和重音符號谒撼,請?jiān)谶@些運(yùn)算符后使用[c],[d]選項(xiàng)雾狈。其中[c]是不區(qū)分大小寫廓潜,[d]是不區(qū)分重音符號,其寫在字符串比較運(yùn)算符之后善榛,比如:name LIKE[cd] 'cafe'辩蛋,那么不論name是cafe、Cafe還是café上面的表達(dá)式都會(huì)返回YES移盆。
4.集合運(yùn)算符
ANY悼院、SOME:集合中任意一個(gè)元素滿足條件,就返回YES咒循。
ALL:集合中所有元素都滿足條件据途,才返回YES钮呀。
NONE:集合中沒有任何元素滿足條件就返回YES。如:NONE person.age < 18昨凡,表示person集合中所有元素的age>=18時(shí)爽醋,才返回YES。
IN:等價(jià)于SQL語句中的IN運(yùn)算符便脊,只有當(dāng)左邊表達(dá)式或值出現(xiàn)在右邊的集合中才會(huì)返回YES蚂四。我們通過一個(gè)例子來看一下
NSArray *filterArray = @[@"ab", @"abc"];
NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);
代碼的作用是將array中和filterArray中相同的元素去除,輸出為:
2016-01-07 13:17:43.669 PredicteDemo[6701:136206] (
a,
abcd
)
array[index]:返回array數(shù)組中index索引處的元素
array[FIRST]:返回array數(shù)組中第一個(gè)元素
array[LAST]:返回array數(shù)組中最后一個(gè)元素
array[SIZE]:返回array數(shù)組中元素的個(gè)數(shù)
5.直接量
在謂詞表達(dá)式中可以使用如下直接量
FALSE哪痰、NO:代表邏輯假
TRUE遂赠、YES:代表邏輯真
NULL、NIL:代表空值
SELF:代表正在被判斷的對象自身
"string"或'string':代表字符串
數(shù)組:和c中的寫法相同晌杰,如:{'one', 'two', 'three'}跷睦。
數(shù)值:包括證書、小數(shù)和科學(xué)計(jì)數(shù)法表示的形式
十六進(jìn)制數(shù):0x開頭的數(shù)字
八進(jìn)制:0o開頭的數(shù)字
二進(jìn)制:0b開頭的數(shù)字
6.保留字
下列單詞都是保留字(不論大小寫)
AND肋演、OR抑诸、IN、NOT爹殊、ALL蜕乡、ANY、SOME梗夸、NONE层玲、LIKE、CASEINSENSITIVE反症、CI辛块、MATCHES、CONTAINS铅碍、BEGINSWITH润绵、ENDSWITH、BETWEEN该酗、NULL授药、NIL士嚎、SELF呜魄、TRUE、YES莱衩、FALSE爵嗅、NO、FIRST笨蚁、LAST睹晒、SIZE趟庄、ANYKEY、SUBQUERY伪很、CAST戚啥、TRUEPREDICATE、FALSEPREDICATE
注:雖然大小寫都可以锉试,但是更推薦使用大寫來表示這些保留字
二猫十、謂詞的用法
1.定義謂詞
一般我們使用下列方法來定義一個(gè)謂詞
1
NSPredicate *predicate = [NSPredicate predicateWithFormat:];
下面我們通過幾個(gè)簡單的例子來看看它該如何使用:
首先我們需要定義一個(gè)模型,因?yàn)槭纠行枰玫剿?/p>
ZLPersonModel.h
#import typedef NS_ENUM(NSInteger, ZLPersonSex) {
ZLPersonSexMale = 0,
ZLPersonSexFamale
};
@interface ZLPersonModel : NSObject
/** NSString 姓名 */
@property (nonatomic, copy) NSString *name;
/** NSUInteger 年齡 */
@property (nonatomic, assign) NSUInteger age;
/** ZLPersonSex 性別 */
@property (nonatomic, assign) ZLPersonSex sex;
+ (instancetype)personWithName:(NSString *)name age:(NSUInteger)age sex:(ZLPersonSex)sex;
@end
下面讓我們進(jìn)入正題
例一:(最簡單的使用)
ZLPersonModel *sunnyzl = [ZLPersonModel personWithName:@"sunnyzl" age:29 sex:ZLPersonSexMale];
ZLPersonModel *jack = [ZLPersonModel personWithName:@"jack" age:22 sex:ZLPersonSexMale];
//? 首先我們來看一些簡單的使用
//? 1.判斷姓名是否是以s開頭的
NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"name LIKE 's*'"];
//? 輸出為:sunnyzl:1, jack:0
NSLog(@"sunnyzl:%d, jack:%d", [pred1 evaluateWithObject:sunnyzl], [pred1 evaluateWithObject:jack]);
//? 2.判斷年齡是否大于25
NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"age > 25"];
//? 輸出為:sunnyzl的年齡是否大于25:1, jack的年齡是否大于25:0
NSLog(@"sunnyzl的年齡是否大于25:%d, jack的年齡是否大于25:%d", [pred2 evaluateWithObject:sunnyzl], [pred2 evaluateWithObject:jack]);
看到這里我們會(huì)發(fā)現(xiàn)evaluateWithObject:方法返回的是一個(gè)BOOL值呆盖,如果符合條件就返回YES拖云,不符合就返回NO。而即使是最簡單的使用也有一些大用處应又,比如以前我們寫判斷手機(jī)號碼宙项、郵編等等,像我就喜歡用John Engelhart大神的RegexKitLite株扛,然而由于年代久遠(yuǎn)需要導(dǎo)入libicucore.dylib庫(xcode7為libicucore.tbd)且由于是mrc又需要添加-fno-objc-arc尤筐,至此我們才能使用。然而使用謂詞讓我們可以用同樣簡潔的代碼實(shí)現(xiàn)相同的功能
例二:判斷手機(jī)號是否正確
- (BOOL)checkPhoneNumber:(NSString *)phoneNumber
{
NSString *regex = @"^[1][3-8]\\d{9}$";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
return [pred evaluateWithObject:phoneNumber];
}
看到這里是不是感覺好爽洞就,感覺以前所有的正則都可以這么匹配叔磷,但是謂詞匹配正則時(shí)也是有缺點(diǎn)的,下面通過一個(gè)例子來看一下這個(gè)致命的缺點(diǎn)
例三:謂詞匹配正則的缺點(diǎn)
(本意:檢測字符串中是否有特殊字符)
- (BOOL)checkSpecialCharacter:(NSString *)string
{
NSString *regex = @"[`~!@#$^&*()=|{}':;',\\[\\].<>/?~奖磁!@#¥……&*()——|{}【】‘改基;:”“'。咖为,秕狰、?]";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
return [pred evaluateWithObject:string];
}
我們想要的效果是字符串中有特殊字符時(shí)就返回YES躁染,然而夢想是美好的鸣哀,現(xiàn)實(shí)是殘酷的
讓我們看看這悲催的結(jié)局
NSString *testString = @"!";
NSLog(@"是否含有特殊字符:%d", [self checkSpecialCharacter:testString]);
//? 當(dāng)testString為一個(gè)特殊字符時(shí),我們驚喜的發(fā)現(xiàn)輸出為
//? 是否含有特殊字符:1
看到這里我們心里猛然一喜吞彤,這tmd根本沒問題嘛
讓我們修改下testString的值
NSString *testString = @"!~";
NSLog(@"%d", [self checkSpecialCharacter:testString]);
//? 我們會(huì)發(fā)現(xiàn)悲催的結(jié)局來了輸出為
//? 是否含有特殊字符:0
再次修改testString的值
NSString *testString = @"abc!~d";
NSLog(@"%d", [self checkSpecialCharacter:testString]);
//? 我們會(huì)發(fā)現(xiàn)輸出為
//? 是否含有特殊字符:0
這總與我們的想法事與愿違味赃,看到這里我們會(huì)發(fā)現(xiàn)謂詞對正則并不像我們使用NSRegularExpression時(shí)匹配的那么好,究其原因是為什么呢渴杆?我們用NSRegularExpression時(shí)會(huì)發(fā)現(xiàn)匹配到一個(gè)結(jié)果時(shí)就會(huì)存入數(shù)組墓陈,再從匹配到的位置繼續(xù)向下匹配。
然而NSPredicate并不會(huì)做這樣的自動(dòng)操作埋嵌,我們最終發(fā)現(xiàn)在NSPredicate輸入[`~!@#$^&*()=|{}':;',\[\].<>/?~破加!@#¥……&*()——|{}【】‘;:”“'雹嗦。范舀,合是、?]正則表達(dá)式時(shí)和寫成^[`~!@#$^&*()=|{}':;',\[\].<>/?~锭环!@#¥……&*()——|{}【】‘聪全;:”“'。辅辩,荔烧、?]$的效果是一樣的汽久。
所以通過這個(gè)例子我們總結(jié)出來鹤竭,只有在正則表達(dá)式為^表達(dá)式$時(shí)才使用謂詞,而不是所有情況都使用景醇。
那么我們是不是因?yàn)檫@一點(diǎn)就摒棄它了呢臀稚,答案是否定的。因?yàn)殡m然NSPredicate有這么一點(diǎn)瑕疵三痰,但是它總體帶給我們的便利其實(shí)除了正則表達(dá)式匹配時(shí)的這個(gè)問題外是更多的吧寺。
2.使用謂詞過濾集合
此部分是我們需要掌握的重點(diǎn),因?yàn)閺倪@里我們就可以看到謂詞的真正的強(qiáng)大之處
其實(shí)謂詞本身就代表了一個(gè)邏輯條件散劫,計(jì)算謂詞之后返回的結(jié)果永遠(yuǎn)為BOOL類型的值稚机。而謂詞最常用的功能就是對集合進(jìn)行過濾。當(dāng)程序使用謂詞對集合元素進(jìn)行過濾時(shí)获搏,程序會(huì)自動(dòng)遍歷其元素赖条,并根據(jù)集合元素來計(jì)算謂詞的值,當(dāng)這個(gè)集合中的元素計(jì)算謂詞并返回YES時(shí)常熙,這個(gè)元素才會(huì)被保留下來纬乍。請注意程序會(huì)自動(dòng)遍歷其元素,它會(huì)將自動(dòng)遍歷過之后返回為YES的值重新組合成一個(gè)集合返回裸卫。
其實(shí)類似于我們使用tableView設(shè)置索引時(shí)使用的下段代碼
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [self.cityGroup valueForKey:@"title"];
}
中的[self.cityGroup valueForKey:@"title"]仿贬。它的作用是遍歷所有title并將得到的值組成新的數(shù)組。
NSArray提供了如下方法使用謂詞來過濾集合
- (NSArray*)filteredArrayUsingPredicate:(NSPredicate *)predicate:使用指定的謂詞過濾NSArray集合墓贿,返回符合條件的元素組成的新集合
NSMutableArray提供了如下方法使用謂詞來過濾集合
- (void)filterUsingPredicate:(NSPredicate *)predicate:使用指定的謂詞過濾NSMutableArray茧泪,剔除集合中不符合條件的元素
NSSet提供了如下方法使用謂詞來過濾集合
- (NSSet*)filteredSetUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):作用同NSArray中的方法
NSMutableSet提供了如下方法使用謂詞來過濾集合
- (void)filterUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):作用同NSMutableArray中的方法。
通過上面的描述可以看出聋袋,使用謂詞過濾不可變集合和可變集合的區(qū)別是:過濾不可變集合時(shí)队伟,會(huì)返回符合條件的集合元素組成的新集合;過濾可變集合時(shí)舱馅,沒有返回值缰泡,會(huì)直接剔除不符合條件的集合元素
下面讓我們來看幾個(gè)例子:
例一:
NSMutableArray *arrayM = [@[@20, @40, @50, @30, @60, @70] mutableCopy];
//? 過濾大于50的值
NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"SELF > 50"];
[arrayM filterUsingPredicate:pred1];
NSLog(@"arrayM:%@", arrayM);
NSArray *array = @[[ZLPersonModel personWithName:@"Jack" age:20 sex:ZLPersonSexMale],
[ZLPersonModel personWithName:@"Rose" age:22 sex:ZLPersonSexFamale],
[ZLPersonModel personWithName:@"Jackson" age:30 sex:ZLPersonSexMale],
[ZLPersonModel personWithName:@"Johnson" age:35 sex:ZLPersonSexMale]];
//? 要求取出包含‘son’的元素
NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"name CONTAINS 'son'"];
NSArray *newArray = [array filteredArrayUsingPredicate:pred2];
NSLog(@"%@", newArray);
輸出為
2016-01-07 16:50:09.510 PredicteDemo[13660:293822] arrayM:(
60,
70
)
2016-01-07 16:50:09.511 PredicteDemo[13660:293822] (
"[name = Jackson, age = 30, sex = 0]",
"[name = Johnson, age = 35, sex = 0]"
)
從這個(gè)例子我們就可以看到NSPredicate有多么強(qiáng)大,如果讓我們用其他的方法來實(shí)現(xiàn)又是一大堆if...else代嗤。
讓我們來回顧一下上面的從第二個(gè)數(shù)組中去除第一個(gè)數(shù)組中相同的元素
例二:
NSArray *filterArray = @[@"ab", @"abc"];
NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);
輸出為:
2016-01-07 13:17:43.669 PredicteDemo[6701:136206] (
a,
abcd
)
如果我們不用NSPredicate的話棘钞,肯定又是各種if...else,for循環(huán)等等干毅∫瞬拢可以看出NSPredicate的出現(xiàn)為我們節(jié)省了大量的時(shí)間和精力。
3.在謂詞中使用占位符參數(shù)
我們上面所有的例子中謂詞總是固定的硝逢,然而我們在現(xiàn)實(shí)中處理變量時(shí)決定了謂詞應(yīng)該是可變的姨拥。下面我們來看看如果讓謂詞變化起來。
首先如果我們想在謂詞表達(dá)式中使用變量渠鸽,那么我們需要了解下列兩種占位符:
%K:用于動(dòng)態(tài)傳入屬性名
%@:用于動(dòng)態(tài)設(shè)置屬性值
其實(shí)相當(dāng)于變量名與變量值
除此之外叫乌,還可以在謂詞表達(dá)式中使用動(dòng)態(tài)改變的屬性值,就像環(huán)境變量一樣
1
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS $VALUE"];
上述表達(dá)式中徽缚,$VALUE是一個(gè)可以動(dòng)態(tài)變化的值憨奸,它其實(shí)最后是在字典中的一個(gè)key,所以可以根據(jù)你的需要寫不同的值凿试,但是必須有$開頭排宰,隨著程序改變$VALUE這個(gè)謂詞表達(dá)式的比較條件就可以動(dòng)態(tài)改變。
下面我們通過一個(gè)例子來看看這三個(gè)重要的占位符應(yīng)該如何使用
例一:
NSArray *array = @[[ZLPersonModel personWithName:@"Jack" age:20 sex:ZLPersonSexMale],
[ZLPersonModel personWithName:@"Rose" age:22 sex:ZLPersonSexFamale],
[ZLPersonModel personWithName:@"Jackson" age:30 sex:ZLPersonSexMale],
[ZLPersonModel personWithName:@"Johnson" age:35 sex:ZLPersonSexMale]];
//? 定義一個(gè)property來存放屬性名那婉,定義一個(gè)value來存放值
NSString *property = @"name";
NSString *value = @"Jack";
//? 該謂詞的作用是如果元素中property屬性含有值value時(shí)就取出放入新的數(shù)組內(nèi)板甘,這里是name包含Jack
NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K CONTAINS %@", property, value];
NSArray *newArray = [array filteredArrayUsingPredicate:pred];
NSLog(@"newArray:%@", newArray);
//? 創(chuàng)建謂詞,屬性名改為age详炬,要求這個(gè)age包含$VALUE字符串
NSPredicate *predTemp = [NSPredicate predicateWithFormat:@"%K > $VALUE", @"age"];
// 指定$SUBSTR的值為 25? ? 這里注釋中的$SUBSTR改為$VALUE
NSPredicate *pred1 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @25}];
NSArray *newArray1 = [array filteredArrayUsingPredicate:pred1];
NSLog(@"newArray1:%@", newArray1);
//? 修改 $SUBSTR的值為32盐类,? 這里注釋中的SUBSTR改為$VALUE
NSPredicate *pred2 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @32}];
NSArray *newArray2 = [array filteredArrayUsingPredicate:pred2];
NSLog(@"newArray2:%@", newArray2);
輸出為
2016-01-07 17:28:02.062 PredicteDemo[14542:309494] newArray:(
"[name = Jack, age = 20, sex = 0]",
"[name = Jackson, age = 30, sex = 0]"
)
2016-01-07 17:28:02.063 PredicteDemo[14542:309494] newArray1:(
"[name = Jackson, age = 30, sex = 0]",
"[name = Johnson, age = 35, sex = 0]"
)
2016-01-07 17:28:02.063 PredicteDemo[14542:309494] newArray2:(
"[name = Johnson, age = 35, sex = 0]"
)
從上例中我們主要可以看出來%K和$VALUE的含義。