DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Data Engineering
  3. Data
  4. Using NSPredicate to Filter Data

Using NSPredicate to Filter Data

Peter Friese user avatar by
Peter Friese
·
Apr. 27, 11 · Interview
Like (0)
Save
Tweet
Share
4.61K Views

Join the DZone community and get the full member experience.

Join For Free

Filtering data is one of the essential tasks in computing. With all the data available today, we need to apply certain limits and constraints to actually make it usable. What use is it to be able to scroll down a list of literally thousands of list items when you really care about one or two of them? Filtering and searching information make up a significant part of our work day - each time you use Google, you're applying a filter to the huge set of data we call the internet.

Even on your local computer, you use services like Spotlight or the search field in your mail application all the time. Apps that lack decent searching and filtering capabilities sometimes are really hard to use, so as developers we should spend some time on thinking how to allow users to filter the data they're dealing with.

In this post, I am going to focus on ways to filter data. We won't be looking at the UI side of things - this is something I'll do in a subsequent blog post.

Old-skool filtering

If you look at an arbitrary code base, chances are you'll sooner or later run into a piece of code similar to this one:

NSMutableArray *oldSkoolFiltered = [[NSMutableArray alloc] init];
for (Book *book in bookshelf) {
if ([book.publisher isEqualToString:@"Apress"]) {
[oldSkoolFiltered addObject:book];
}
}

It's a straight-forward approach to filtering an array of items (in this case, we're talking about books) using a rather simple if-statement. Nothing wrong with this, but despite the fact we're using a fairly simple expression here, the code is rather verbose. We can easily imagine what will happen in case we need to use more complicated selection criteria or a combination of filtering criteria.

Simple filtering with NSPredicate

Thanks to Cocoa, we can simplify the code by using NSPredicate. NSPredicate is the object representation of an if-statement, or, more formally, a predicate.

Predicates are expressions that evaluate to a truth value, i.e. true or false. We can use them to perform validation and filtering. In Cocoa, we can use NSPredicate to evaluate single objects, filter arrays and perform queries against Core Data data sets.

Let's have a look at how our example looks like when using NSPredicate:

NSPredicate *predicate =
[NSPredicate predicateWithFormat:@"publisher == %@", @"Apress" ];
NSArray *filtered = [bookshelf filteredArrayUsingPredicate:predicate];

Much shorter and better readable!

Filtering with Regular Expressions

Regular Expressions can be used to solve almost any problem ;-) so it's good to know you can use them in NSPredicates as well. To use regular expressions in your NSPredicate, you need to use the MATCHES operator.

Let's filter all books that are about iPad or iPhone programming:

predicate = [NSPredicate predicateWithFormat:@"title MATCHES '.*(iPhone|iPad).*'"];
filtered = [bookshelf filteredArrayUsingPredicate:predicate];
dumpBookshelf(@"Books that contain 'iPad' or 'iPhone' in their title", filtered);

You need to obey some rules when using regular expressions in NSPredicate: most importantly, you cannot use regular expression metacharacters inside a pattern set.

Filtering using set operations

Let's for a moment assume you want to filter all books that have been published by your favorite publishers. Using the IN operator, this is rather simple: first, we need to set up a set containing the publishers we're interested in. Then, we can create the predicate and finally perform the filtering operation:

NSArray *favoritePublishers = [NSArray arrayWithObjects:@"Apress", @"O'Reilly", nil];
predicate = [NSPredicate predicateWithFormat:@"publisher IN %@", favoritePublishers];
filtered = [bookshelf filteredArrayUsingPredicate:predicate];
dumpBookshelf(@"Books published by my favorite publishers", filtered);

Advanced filtering thanks to KVC goodness

NSPredicate relies on key-value coding to achieve it's magic. On one hand this means your classes need to be KVC compliant in order to be queried using NSPredicate (at least the attributes you want to query). On the other hand, this allows us to perform some very interesting things with very little lines of code.

Let's for example retrieve a list of books written by authors with the name "Mark":

predicate =
[NSPredicate predicateWithFormat:@"authors.lastName CONTAINS %@", @"Mark" ];
filtered = [bookshelf filteredArrayUsingPredicate:predicate];

In case we'd want to return the value of one of the aggregate functions, we don't need to use NSPredicate itself, but instead use KVC directly. Let's retrieve the average price of all books on our shelf:

NSNumber *average = [bookshelf valueForKeyPath:@"@avg.price"];

Conclusion

The Cocoa libraries provide some very powerful abstractions which can make your life and that of the people reading your code much easier. It pays off to know about them, so go ahead and browse the Cocoa documentation and hunt for those gems!

Apple's NSPredicate programming guide provides an in-depth documentation for NSPredicate containing all the things I didn't cover in this post.

NSPredicate also plays an important role when querying data in Core Data, something we will need to have a look at in one of the next blog posts. Stay tuned!

Code

The code for this post is available on my github page: get forking!

 

From http://www.peterfriese.de/using-nspredicate-to-filter-data/

Data (computing) Filter (software)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Real-Time Analytics for IoT
  • Custom Validators in Quarkus
  • Building Microservice in Golang
  • How To Build a Spring Boot GraalVM Image

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: