Wednesday, June 29, 2016

Objective C NSPredicate Part 2/4

In the first part, We have seen some Basic comparisons using NSPredicate. In this part, Let' see some String comparisons.


CONTAINS:



   
NSArray *arr = @[@"Ápple",@"Mango",@"Banana",@"Papaya"];


In the above array let's filter the elements contains the word 'ap'.


   
 NSPredicate *contains = [NSPredicate predicateWithFormat:
                                                               @"SELF CONTAINS %@",  @"ap"];
  
    NSArray *filteredArr = [arr filteredArrayUsingPredicate:contains];
    
    NSLog(@"filteredArr-Contains : %@",filteredArr);

    filteredArr-Loop : (

         Papaya
    ) 


Above predicate is supposed to filter Ápple and Papaya. But it filtered only Papaya though Ápple is having 'ap' word. 






The reason is, We have not considered case sensitive here. As A in Apple is in capital, predicate couldn't filter in. We can make the filtration case insensitive by explicitly saying,



   
NSPredicate *contains = [NSPredicate predicateWithFormat:
                                                                   @"SELF CONTAINS[c] %@",  @"ap"];



Here, [c] in the predicate is making the filtration case insensitive.

Let's try this predicate on the array,


   
 NSArray *arr = @[@"Ápple",@"Mango",@"Banana",@"Papaya"];

    NSPredicate *contains = [NSPredicate predicateWithFormat:
                                                                        @"SELF CONTAINS[c] %@",  @"ap"];
  
    NSArray *filteredArr = [arr filteredArrayUsingPredicate:contains];
    
    NSLog(@"filteredArr-Contains[c] : %@",filteredArr);

    filteredArr-Contains[c] : (

         Papaya
    )


No luck :(

Still we got only Papaya. If we look at the fruit Ápple, It is having a accent sign (Diacritic). 

Here is the meaning for Diacritic. 



  
noun
  1. a sign, such as an accent or cedilla, which when written above or below a letter indicates a difference in pronunciation from the same letter when unmarked or differently marked.
  adjective
  1. 1.
    (of a mark or sign) indicating a difference in pronunciation.



We can make the filtration Diacritic insensitive by giving [d] in the predicate. As we need both case and diacritic insensitive filter, Let's aa both in the predicate and try with our array.


   
 NSArray *arr = @[@"Ápple",@"Mango",@"Banana",@"Papaya"];
    
    NSPredicate *contains = [NSPredicate predicateWithFormat:
                                                             @"SELF CONTAINS[cd] %@",  @"ap"];
  
    NSArray *filteredArr = [arr filteredArrayUsingPredicate:contains];
    
    NSLog(@"filteredArr-Contains[cd] : %@", filteredArr);

    filteredArr-Contains[cd] : (

          "\U00c1pple",
           Papaya
     )  


Finally, Our predicate worked as expected though the filtered array is having the unicode for that diacritic letter.

BEGINSWITH:


   
 NSArray *arr = @[@"Ápple",@"Mango",@"Papaya",@"PineApple",@"Apricot"];
    
    NSPredicate *contains = [NSPredicate predicateWithFormat:
                                                              @"SELF BEGINSWITH[cd] %@",  @"ap"];
  
    NSArray *filteredArr = [arr filteredArrayUsingPredicate:contains];
    
    NSLog(@"filteredArr-BEGINSWITH[cd] : %@",filteredArr);

    filteredArr-BEGINSWITH[cd] : (

         "\U00c1pple",
         Apricot
    )



ENDSWITH:
    

  
  NSArray *arr = @[@"Ápple",@"Mango",@"Papaya",@"PineApple",@"Apricot"];
    
    NSPredicate *contains = [NSPredicate predicateWithFormat:
                                                             @"SELF ENDSWITH[cd] %@",  @"le"];
  
    NSArray *filteredArr = [arr filteredArrayUsingPredicate:contains];
    
    NSLog(@"filteredArr-ENDSWITH[cd] : %@",filteredArr);

    filteredArr-ENDSWITH[cd] : (

          "\U00c1pple",
          PineApple
    )



MATCHES:


   
 NSArray *arr = @[@"Ápple",@"Mango",@"Papaya",@"PineApple",@"Apricot"];
    
    NSPredicate *contains = [NSPredicate predicateWithFormat:
                                                               @"SELF MATCHES[cd] %@",  @"APPle"];
  
    NSArray *filteredArr = [arr filteredArrayUsingPredicate:contains];
    
    NSLog(@"filteredArr-MATCHES[cd] : %@",filteredArr);


     filteredArr-MATCHES[cd] : (

            "\U00c1pple"
      )


LIKE:

LIKE comparison is very useful along with wildcard characters like * and ?.

This comparison is useful for fetching particular patterns.

We can use LIKE comparison as a replacement for below comparisons.

  1. BEGINSWITH
  2. ENDSWITH
  3. CONTAINS


  
NSArray *arr = @[@"111.png",@"121.png",@"111.jpg",@"222.gif"];



Filter all the images starting with '11' (BEGINSWITH) :



    
NSArray *arr = @[@"111.png",@"121.png",@"111.jpg",@"222.gif"];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                                                       @"SELF LIKE %@"@"11*"];

    NSArray *filteredArr = [arr filteredArrayUsingPredicate:predicate];
    
    NSLog(@"filteredArr-LIKE : %@",filteredArr.description);

     filteredArr-LIKE : (

          "111.png",
          "111.jpg"
      )



Filter all the images ending with 'jpg' (ENDSWITH) :



   
 NSArray *arr = @[@"111.png",@"121.png",@"111.jpg",@"222.gif"];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                                                   @"SELF LIKE %@"@"*.jpg"];

    NSArray *filteredArr = [arr filteredArrayUsingPredicate:predicate];
    
    NSLog(@"filteredArr-LIKE : %@",filteredArr.description);


       filteredArr-LIKE : (

             "111.jpg"
      )



Filter all the images containing 'png' (CONTAINS) :



   
 NSArray *arr = @[@"111.png",@"121.png",@"111.jpg",@"222.gif"];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                                                    @"SELF LIKE %@"@"*png*"];

    NSArray *filteredArr = [arr filteredArrayUsingPredicate:predicate];
    
    NSLog(@"filteredArr-LIKE : %@",filteredArr.description);

     filteredArr-LIKE : (

           "111.png",
           "121.png"
     )



As I said LIKE is very useful for most of the comparisons.


  • *111* means, element may have any thing before '111' and after '111'
  • *111 means, element may have any thing before '111', but shouldn't have anything at the end.
  • 111* means, element may have any thing at the end but shouldn't have anything before.






* takes any number of characters before and after, Where as ? considers only one character.



    
NSArray *arr = @[@"happy-1.png",@"sad-1.png",@"happy-22.png",@"sad-2.png"];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                                             @"SELF like %@"@"happy-*.png"];
    
    NSArray *results = [arr filteredArrayUsingPredicate:predicate];
    NSLog(@"filteredArr ---- * : %@",results.description);

     filteredArr---- * : (

         "happy-1.png",
         "happy-22.png"
     )




    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                                              @"SELF like %@"@"happy-?.png"];
    
    NSArray *results = [arr filteredArrayUsingPredicate:predicate];
    NSLog(@"filteredArr ---- ? : %@",results.description);


     filteredArr ---- ? : (

         "happy-1.png"

     )


In the next part, Let' see some compound comparisons.


Hope this post is useful. Feel free to comment in case of any queries.