謂詞NSpredict使用 模糊查詢 過濾信息

前言

在開發(fā)中秩霍,我們經(jīng)常會遇到一些需要宵呛,讓我們從集合中查找某個(gè)值单匣,從集合中過濾想要的內(nèi)容等等,因而我們就需要遍歷集合宝穗,加條件判斷户秤,然后獲取符合條件的值。而關(guān)于集合的遍歷是所有軟件開發(fā)從業(yè)人員經(jīng)常打交道的一些事情逮矛。

把范圍縮小到iOS開發(fā)中鸡号,關(guān)于集合地遍歷的方法就有好多種,人們一直在討論和爭辯须鼎,想尋找出一種最快最有效的方法鲸伴,是用for循環(huán),還是block晋控,是用并發(fā)操作汞窗,還是順序操作,等等赡译。甚至有人不惜使用大數(shù)據(jù)量來測試各種遍歷方式的效率以及精確度仲吏。

NSPredicate
一種類似于SQL語句來過濾集合內(nèi)容的方式從而避免了自己進(jìn)行集合遍歷的方法,就是NSPredicate。蘋果在Cocoa touch框架給我們提供了NSPredicate這個(gè)類裹唆,封裝了一些讓我們可以直接對集合設(shè)置過濾條件的方法誓斥,而至于蘋果是如何在SDK中進(jìn)行數(shù)據(jù)查找地,我們并不需要關(guān)心许帐,因?yàn)槲蚁嘈潘龅囊欢ū任覀兒冕场W(xué)過SQL語法的人,使用NSPredicate會十分容易舞吭。下面詳細(xì)的講述NSPredicate的語法規(guī)則。

簡單說明

NSPredict 謂詞可以通過定義一個(gè)邏輯條件析珊,來搜索查詢羡鸥、過濾信息
NSPredict主要包含三個(gè)子類:NSComparisonPredicate、NSCompoundPredicate忠寻、NSExpression

NSPredict 表達(dá)式

在介紹NSPredict的使用之前惧浴,我們必須先要了解如何正確的書寫謂詞表達(dá)式

比較運(yùn)算符

= 、 == (判斷兩個(gè)表達(dá)式是否相等)

=>奕剃、>= (左側(cè)表達(dá)式是否大于或等于右側(cè)表達(dá)式)

<= 衷旅、 =< (左側(cè)表達(dá)式是否小于或等于右側(cè)表達(dá)式)

< 、 > (左側(cè)表達(dá)式是否大于纵朋、小于右側(cè)表達(dá)式)

柿顶!= 、<> (兩個(gè)表達(dá)式是否不相等)

BETWEEN (”表達(dá)式 BEYWEEN {最小值操软,最大值}“ 嘁锯,表達(dá)式必須大于等于最小值或小于等于最大值)

邏輯運(yùn)算符

AND、&& (兩個(gè)表達(dá)式都為真是聂薪,結(jié)果為真家乘;有假則結(jié)果為假)

OR、|| (兩個(gè)表達(dá)式有一個(gè)結(jié)果為真藏澳,結(jié)果為真仁锯;同為假,則結(jié)果為假)

NOT 翔悠、业崖! ( 表達(dá)式結(jié)果取反)

字符串比較運(yùn)算符

BEGINSWITH (字符串是否以某一子字符串開頭)

ENDSWITH (字符串是否以某一子字符串結(jié)尾)

CONTAINS (字符串是否包含某一子字符串)

LIKE (字符串是否匹配指定的字符串模板)

      title LIKE *abc? :title現(xiàn)有任意多的字符串,結(jié)尾必須為abc+任意一個(gè)字符

MATCHES (字符串是否匹配指定的正則表達(dá)式蓄愁;正則表達(dá)式功能強(qiáng)大腻要,但是執(zhí)行效率低。能用謂詞表達(dá)式的就不要用正則表達(dá)式)
注意:字符串比較運(yùn)算符默認(rèn)區(qū)分大小寫和重音符號

1.如果希望字符串比較運(yùn)算符不區(qū)分大小寫涝登,可以再運(yùn)算符后添加[c]
2.如果希望字符串比較運(yùn)算符不區(qū)分重音符號雄家,可以再運(yùn)算符后添加[d]
一般都是在運(yùn)算符后面添加[cd],代表不區(qū)分大小寫和重音符號
集合操作相關(guān)的運(yùn)算符

ANY 、SOME (集合中任意一個(gè)元素滿足條件,返回YES)

ALL (集合中多有元素滿足條件趟济,返回YES)

NONE (集合中任何元素不滿足條件乱投,返回YES)

IN (左邊的表達(dá)式(值) 在右邊的集合中存在,返回YES)

array[index] ( 返回?cái)?shù)組index索引處的元素)

array[FIRST] (返回?cái)?shù)組第一個(gè)元素)

array[LAST] ( 返回?cái)?shù)組最后一個(gè)元素)

array[SIZE] ( 返回?cái)?shù)組元素個(gè)數(shù))

謂詞表達(dá)式中的直接量

FALSE顷编、NO ( 邏輯假)

TRUE戚炫、YES ( 邏輯真)

NULL、NIL ( 空值)

SELF (被判斷的對象本身)

"text"('text') (字符串)

數(shù)組 (數(shù)組元素以英文逗號隔開)

數(shù)值直接量 (整數(shù)媳纬、小數(shù)双肤、科學(xué)技術(shù)法)

各進(jìn)制數(shù) (0x(十六進(jìn)制)、0o(八進(jìn)制)钮惠、0b(二進(jìn)制))

注意:謂詞表達(dá)式中" "與' '效果相同茅糜,但是“ ”與‘ ’應(yīng)該匹配

保留字:大寫單詞是保留字
MATCHES、CONTAINS素挽、BEGINSWITH蔑赘、ENDSWIHT、BETWEEN预明、NULL缩赛、NIL、SELF撰糠、AND酥馍、OR、IN阅酪、NOT物喷、ALL、ANY遮斥、SOME峦失、NONE、LIKE术吗、CASEINSENSITIVE尉辑、CI、TRUE较屿、YES隧魄、FALSE、NO隘蝎、FIRST购啄、LAST、SIZE嘱么、ANYKEY狮含、SUBQUERY、CAST、TRUEPREDICATE几迄、FALSEOREDICATE

謂詞NSPredict實(shí)際使用

(1)對NSArray進(jìn)行過濾

NSPredict 本質(zhì)上就是一個(gè)邏輯條件蔚龙,NSPredict 運(yùn)算的結(jié)果就是一個(gè)BOOL值
NSPredict 一個(gè)比較常用的功能就是對集合元素的過濾; 自動遍歷集合元素------>根據(jù)元素判斷 NSPredict 的結(jié)果------>結(jié)果為YES時(shí),集合元素保存
注意謂詞過濾不可變集合映胁,結(jié)果返回符合條件的新集合木羹;謂詞過濾可變集合,直接將集合中不符合條件的元素去掉

示例1:

NSArray * array = @[@"libai",@"dufu",@"sushi",@"dumu"];
        
        NSPredicate * pred = [NSPredicate predicateWithFormat:@"SELF like %@",@"du*"];
        NSArray * resultArr = [array filteredArrayUsingPredicate:pred];
        NSLog(@"%@",resultArr);//輸出值:(
    dufu,
    dumu
)
  
        NSSet * set = [NSSet setWithObjects:
                                  [[CXHPerson alloc]initWithName:@"li si" Age:@"25"],
                                  [[CXHPerson alloc]initWithName:@"zhang san" Age:@"20"],
                                  [[CXHPerson alloc]initWithName:@"wang wu" Age:@"18"],nil
                                    ];
        
        NSPredicate * pred3 = [NSPredicate predicateWithFormat:@"name CONTAINS 'ang'"];
       NSSet * resultSet = [set filteredSetUsingPredicate:pred3];
        for (CXHPerson * person  in resultSet) {
            NSLog(@"%@",person.name);
        }
 NSArray * array3 = @[[[CXHPerson alloc]initWithName:@"li si" Age:@"25"],
                             [[CXHPerson alloc]initWithName:@"zhang san" Age:@"20"],
                             [[CXHPerson alloc]initWithName:@"wang wu" Age:@"18"]];
        NSArray * array4 = [array3 filteredArrayUsingPredicate:pred3];
        for (CXHPerson * person  in array4) {
            NSLog(@"%@",person.name);
        }
//輸出值:
 zhang san
 wang wu

示例2:

NSArray *array = [[NSArray alloc]initWithObjects:@"beijing",@"shanghai",@"guangzou",@"wuhan", nil];    
NSString *string = @"ang";    
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS %@",string];    
NSLog(@"%@",[array filteredArrayUsingPredicate:pred]);
(2)判斷字符串首字母是否為字母:
NSString *regex = @"[A-Za-z]+";    
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];      
if ([predicate evaluateWithObject:aString]) {  

}
(3)字符串替換:
NSError* error = NULL;    
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:@"(encoding=\"){FNXX==XXFN}+(\")"    
                                                                        options:0    
                                                                        error:&error];    
NSString* sample = @"<xml encoding=\"abc\"></xml><xml encoding=\"def\"></xml><xml encoding=\"ttt\"></xml>";    
NSLog(@"Start:%@",sample);    
NSString* result = [regex stringByReplacingMatchesInString:sample    
                                                  options:0    
                                                   range:NSMakeRange(0, sample.length)    
                                                  withTemplate:@"$1utf-8$2"];    
NSLog(@"Result:%@", result);
(4)截取字符串如下:
//組裝一個(gè)字符串解孙,需要把里面的網(wǎng)址解析出來    
NSString *urlString=@"<meta/><link/><title>1Q84 BOOK1</title></head><body>";    

//NSRegularExpression類里面調(diào)用表達(dá)的方法需要傳遞一個(gè)NSError的參數(shù)坑填。下面定義一個(gè)      
NSError *error;    

//http+:[^\\s]* 這個(gè)表達(dá)式是檢測一個(gè)網(wǎng)址的。(?<=title\>).*(?=</title)截取html文章中的<title></title>中內(nèi)文字的正則表達(dá)式    
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=title\\>).*(?=</title)" options:0 error:&error];    

if (regex != nil) {    
NSTextCheckingResult *firstMatch=[regex firstMatchInString:urlString options:0 range:NSMakeRange(0, [urlString length])];    

    if (firstMatch) {    
        NSRange resultRange = [firstMatch rangeAtIndex:0];    

        //從urlString當(dāng)中截取數(shù)據(jù)    
        NSString *result=[urlString substringWithRange:resultRange];    
        //輸出結(jié)果    
        NSLog(@"->%@<-",result);    
    }    
}
(5)判斷手機(jī)號碼弛姜,電話號碼函數(shù)
// 正則判斷手機(jī)號碼地址格式  
- (BOOL)isMobileNumber:(NSString *)mobileNum  
{  
   /** 
    * 手機(jī)號碼 
    * 移動:134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188 
    * 聯(lián)通:130,131,132,152,155,156,185,186 
    * 電信:133,1349,153,180,189 
    */  
   NSString * MOBILE = @"^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$";  
   /** 
    10         * 中國移動:China Mobile 
    11         * 134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188 
    12         */  
   NSString * CM = @"^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\d)\\d{7}$";  
   /** 
    15         * 中國聯(lián)通:China Unicom 
    16         * 130,131,132,152,155,156,185,186 
    17         */  
   NSString * CU = @"^1(3[0-2]|5[256]|8[56])\\d{8}$";  
   /** 
    20         * 中國電信:China Telecom 
    21         * 133,1349,153,180,189 
    22         */  
   NSString * CT = @"^1((33|53|8[09])[0-9]|349)\\d{7}$";  
   /** 
    25         * 大陸地區(qū)固話及小靈通 
    26         * 區(qū)號:010,020,021,022,023,024,025,027,028,029 
    27         * 號碼:七位或八位 
    28         */  
  // NSString * PHS = @"^0(10|2[0-5789]|\\d{3})\\d{7,8}$";  

   NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];  
   NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];  
   NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU];  
   NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT];  

    if (([regextestmobile evaluateWithObject:mobileNum] == YES)  || ([regextestcm evaluateWithObject:mobileNum] == YES)|| ([regextestct evaluateWithObject:mobileNum] == YES)   || ([regextestcu evaluateWithObject:mobileNum] == YES)) {  
        if([regextestcm evaluateWithObject:mobileNum] == YES) {  
            NSLog(@"China Mobile");  
        } else if([regextestct evaluateWithObject:mobileNum] == YES) {  
            NSLog(@"China Telecom");  
        } else if ([regextestcu evaluateWithObject:mobileNum] == YES) {  
            NSLog(@"China Unicom");  
        } else {  
            NSLog(@"Unknow");  
        }  

      return YES;  

     }  else   {  

      return NO;  
  }  
}
(6)郵箱驗(yàn)證脐瑰、電話號碼驗(yàn)證:
//是否是有效的正則表達(dá)式  

+(BOOL)isValidateRegularExpression:(NSString *)strDestination byExpression:(NSString *)strExpression  {  

   NSPredicate *predicate = [NSPredicatepredicateWithFormat:@"SELF MATCHES %@", strExpression];    

   return [predicate evaluateWithObject:strDestination];  

}  

//驗(yàn)證email  
+(BOOL)isValidateEmail:(NSString *)email {  

   NSString *strRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{1,5}";  

   BOOL rt = [CommonTools isValidateRegularExpression:email byExpression:strRegex];  

   return rt;  

}  

//驗(yàn)證電話號碼  
+(BOOL)isValidateTelNumber:(NSString *)number {  

   NSString *strRegex = @"[0-9]{1,20}";  

   BOOL rt = [CommonTools isValidateRegularExpression:number byExpression:strRegex];  

   return rt;  

}
(7)NSDate進(jìn)行篩選
//日期在十天之內(nèi):  
NSDate *endDate = [[NSDate date] retain];  
NSTimeInterval timeInterval= [endDate timeIntervalSinceReferenceDate];  
timeInterval -=3600*24*10;  
NSDate *beginDate = [[NSDate dateWithTimeIntervalSinceReferenceDate:timeInterval] retain];  
//對coredata進(jìn)行篩選(假設(shè)有fetchRequest)  
NSPredicate *predicate_date = [NSPredicate predicateWithFormat:@"date >= %@ AND date <= %@", beginDate,endDate];  

[fetchRequest setPredicate:predicate_date];  
//釋放retained的對象  
[endDate release];  
[beginDate release];
(8)NSPredict 的占位符參數(shù)

通過使用占位符,在謂詞表達(dá)式中使用變量
%K : 動態(tài)傳入屬性名
%@ : 動態(tài)設(shè)置屬性值
$SUBSTR : 一個(gè)動態(tài)變化的值娱据,可以通過它動態(tài)改變比較條件

//設(shè)置NSPredict 中的可變參數(shù),并計(jì)算結(jié)果
- (BOOL)evaluateWithObject:(nullable id)object substitutionVariables:(nullable NSDictionary<NSString *, id> *)bindings NS_AVAILABLE(10_5, 3_0); // single pass evaluation substituting variables from the bindings dictionary for any variable expressions encountered
//設(shè)置NSPredict 的可變參數(shù)盅惜,返回一個(gè)NSPredict 對象
- (instancetype)predicateWithSubstitutionVariables:(NSDictionary<NSString *, id> *)variables;    // substitute constant values for variables

示例代碼

 CXHPerson * person1 = [[CXHPerson alloc]initWithName:@"zhang san" Age:@"21"];
 CXHPerson * person2 = [[CXHPerson alloc]initWithName:@"li si" Age:@"25"];
CXHPerson * person3 = [[CXHPerson alloc]initWithName:@"stark" Age:@"11"];
        
        CXHPerson * person4 = [[CXHPerson alloc]initWithName:@"sunny" Age:@"30"];
        
         NSArray * array2 = @[person1,person2,person3,person4];
        
        NSString * name = @"age";
        NSString * age = @"3";
        NSPredicate * changePre1 = [NSPredicate predicateWithFormat:@"%K CONTAINS[cd] %@",name,age];
        
    NSArray * newArray2 = [array2 filteredArrayUsingPredicate:changePre1];
        for (CXHPerson * person in newArray2) {
            NSLog(@"newArray2%@----%@",person.name,person.age);
        }
        
        //name中包含$SUBSTR的字串
        NSPredicate * changePre2 = [NSPredicate predicateWithFormat:@"%K CONTAINS[cd] $SUBSTR",@"name"];
        //指定$SUBSTR的值為sun
        NSPredicate * newChangePre2 = [changePre2 predicateWithSubstitutionVariables:@{@"SUBSTR":@"sun"}];
        
        NSArray * newArray3 = [array2 filteredArrayUsingPredicate:newChangePre2];
        for (CXHPerson * person in newArray3) {
            NSLog(@"newArray3%@----%@",person.name,person.age);
        }
        

        NSPredicate * newChangePre3 = [changePre2 predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObjectsAndKeys:@"ang",@"SUBSTR", nil]];
        
        NSArray * newArray4 = [array2 filteredArrayUsingPredicate:newChangePre3];
        for (CXHPerson * person in newArray4) {
            NSLog(@"newArray4%@----%@",person.name,person.age);
        }
//輸出結(jié)果:
2018-02-27 23:07:11.820 CXHNSPredicate[4540:96427] newArray2sunny----30
2018-02-27 23:07:11.820 CXHNSPredicate[4540:96427] newArray3sunny----30
2018-02-27 23:07:11.820 CXHNSPredicate[4540:96427] newArray4zhang san----21

那么至此NSPredicate就到到此介紹完畢中剩。

關(guān)于謂詞的使用,我們只列舉了幾個(gè)常見的用法抒寂,它還有很多種靈活的用法结啼,如對時(shí)間datetime的間隔篩選、謂詞變量 ”謂詞==$變量名“等屈芜,待有時(shí)間希望大家去研究郊愧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市井佑,隨后出現(xiàn)的幾起案子属铁,更是在濱河造成了極大的恐慌,老刑警劉巖躬翁,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焦蘑,死亡現(xiàn)場離奇詭異,居然都是意外死亡盒发,警方通過查閱死者的電腦和手機(jī)例嘱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宁舰,“玉大人拼卵,你說我怎么就攤上這事÷瑁” “怎么了腋腮?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我低葫,道長详羡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任嘿悬,我火速辦了婚禮实柠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘善涨。我一直安慰自己窒盐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布钢拧。 她就那樣靜靜地躺著蟹漓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪源内。 梳的紋絲不亂的頭發(fā)上葡粒,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音膜钓,去河邊找鬼嗽交。 笑死,一個(gè)胖子當(dāng)著我的面吹牛颂斜,可吹牛的內(nèi)容都是我干的夫壁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼沃疮,長吁一口氣:“原來是場噩夢啊……” “哼盒让!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起司蔬,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤邑茄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后俊啼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杏愤,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡链瓦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年搪花,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刁愿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豪墅,死狀恐怖泉手,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情偶器,我是刑警寧澤斩萌,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布缝裤,位于F島的核電站,受9級特大地震影響颊郎,放射性物質(zhì)發(fā)生泄漏憋飞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一姆吭、第九天 我趴在偏房一處隱蔽的房頂上張望榛做。 院中可真熱鬧,春花似錦内狸、人聲如沸检眯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锰瘸。三九已至,卻和暖如春昂灵,著一層夾襖步出監(jiān)牢的瞬間避凝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工眨补, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留管削,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓渤涌,卻偏偏與公主長得像佩谣,于是被迫代替她去往敵國和親把还。 傳聞我的和親對象是個(gè)殘疾皇子实蓬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容