Skip to content

Instantly share code, notes, and snippets.

@icodebuster
Forked from jarsen/NSArrayMagic.m
Created December 1, 2015 16:01
Show Gist options
  • Save icodebuster/e935769ade3bcc766f09 to your computer and use it in GitHub Desktop.
Save icodebuster/e935769ade3bcc766f09 to your computer and use it in GitHub Desktop.
How to do lots of cool things with NSArray. Inspired by NSHipster and WWDC 2013 Session 228 - "Hidden Gems in Cocoa and Cocoa Touch"
NSArray *albums = @[[Album albumWithName:@"Random Access Memories" price:9.99f],
[Album albumWithName:@"Clarity" price:6.99f],
[Album albumWithName:@"Weekend in America" price:7.99f],
[Album albumWithName:@"Weekend in America" price:7.90f],
[Album albumWithName:@"Bangarang EP" price:2.99f]];
// Reversing an Array
__unused NSArray *reversed = albums.reverseObjectEnumerator.allObjects;
// PREDICATES
// Find by name
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name like %@", @"Bangarang EP"]].firstObject name];
// Find by name case and diacritic insenstive
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name like[cd] %@", @"bangaráng ep"]].firstObject name];
// Finding with *?
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name like[cd] %@", @"ba?garán*"]].firstObject name];
// startswith, endswith
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name beginswith[cd] %@", @"bang"]].firstObject name];
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name endswith[cd] %@", @"ies"]].firstObject name];
// contains
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name contains[cd] %@", @"access"]].firstObject name];
// Comparisons (chained up with object operator)
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"price == %f", 9.99f]] valueForKeyPath:@"@unionOfObjects.name"];
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"price < %f", 9.99f]] valueForKeyPath:@"@unionOfObjects.name"];
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"price BETWEEN %@", @[@5, @9]]] valueForKeyPath:@"@unionOfObjects.name"];
// Use %k to subtitute for key paths, because %@'s get wrapped with quotes
[[albums filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%K like 'Clarity'", @"name" ]] valueForKeyPath:@"@unionOfObjects.name"];
// and then there's blocks... easier to read?
[albums filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Album *album, NSDictionary *bindings) {
return [album.name hasPrefix:@"Random"];
}]];
// Simple Collection Operators
// @count: Returns the number of objects in the collection as an NSNumber.
// @sum: Converts each object in the collection to a double, computes the sum, and returns the sum as an NSNumber.
// @avg: Takes the double value of each object in the collection, and returns the average value as an NSNumber.
// @max/@Min: Determines the maximum value using compare:. Objects must support comparison with one another for this to work.
NSArray *numArray = @[@1, @2, @3, @4, @5]; // NSNumbers are a little different than objects with properties, use .self
[numArray valueForKeyPath:@"@sum.self"];
[numArray valueForKeyPath:@"@avg.self"];
[numArray valueForKeyPath:@"@min.self"];
[numArray valueForKeyPath:@"@max.self"];
[numArray valueForKeyPath:@"@count.self"];
[albums valueForKeyPath:@"@sum.price"];
[albums valueForKeyPath:@"@avg.price"];
[albums valueForKeyPath:@"@min.price"];
[albums valueForKeyPath:@"@max.name"];
// Object Operator
// @unionOfObjects / @distinctUnionOfObjects: Returns an array of the objects in the property specified in the key
// path to the right of the operator. @distinctUnionOfObjects removes duplicates, whereas @unionOfObjects does not.
// Important: This operator raises an exception if any of the leaf objects is nil.
[albums valueForKeyPath:@"@unionOfObjects.name"];
[albums valueForKeyPath:@"@distinctUnionOfObjects.name"];
NSArray *albums2 = @[[Album albumWithName:@"Random Access Memories" price:9.99f],
[Album albumWithName:@"Clarity" price:6.99f],
[Album albumWithName:@"Hear No Evil" price:7.90f],
[Album albumWithName:@"Hear No Evil" price:7.90f]];
// @distinctUnionOfArrays / @unionOfArrays: Returns an array containing the combined values of each array in the collection,
// as specified by the key path to the right of the operator. As you'd expect, the distinct version removes duplicate values.
// @distinctUnionOfSets: Similar to @distinctUnionOfArrays, but it expects an NSSet containing NSSet objects, and returns an NSSet.
// Because sets can't contain duplicate values anyway, there is only the distinct operator.
[@[albums, albums2] valueForKeyPath:@"@unionOfArrays.name"];
[@[albums, albums2] valueForKeyPath:@"@distinctUnionOfArrays.name"];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment