Permalink
Browse files

add ma_sorted: method and corresponding SORTED macro

  • Loading branch information...
1 parent cce4b0a commit 0f680db6f852fb53b908bf7a6565a38b65194933 @mikeash committed Feb 13, 2012
Showing with 41 additions and 0 deletions.
  1. +6 −0 MACollectionUtilities.h
  2. +17 −0 MACollectionUtilities.m
  3. +6 −0 README.markdown
  4. +12 −0 main.m
View
@@ -34,13 +34,17 @@
#define EACH(array) MAEachHelper(array, &MA_eachTable)
+#define SORTED(collection, ...) [collection ma_sorted: ^BOOL (id a, id b) { return (__VA_ARGS__) != 0; }]
+
@interface NSArray (MACollectionUtilities)
- (NSArray *)ma_map: (id (^)(id obj))block;
- (NSArray *)ma_select: (BOOL (^)(id obj))block;
- (id)ma_match: (BOOL (^)(id obj))block;
- (id)ma_reduce: (id)initial block: (id (^)(id a, id b))block;
+- (NSArray *)ma_sorted: (BOOL (^)(id a, id b))lessThan;
+
@end
@interface NSSet (MACollectionUtilities)
@@ -49,6 +53,8 @@
- (NSSet *)ma_select: (BOOL (^)(id obj))block;
- (id)ma_match: (BOOL (^)(id obj))block;
+- (NSArray *)ma_sorted: (BOOL (^)(id a, id b))lessThan;
+
@end
View
@@ -44,6 +44,18 @@ - (id)ma_reduce: (id)initial block: (id (^)(id a, id b))block
return a;
}
+- (NSArray *)ma_sorted: (BOOL (^)(id a, id b))lessThan
+{
+ return [self sortedArrayUsingComparator: ^NSComparisonResult(id a, id b) {
+ if(lessThan(a, b))
+ return NSOrderedAscending;
+ else if(lessThan(b, a))
+ return NSOrderedDescending;
+ else
+ return NSOrderedSame;
+ }];
+}
+
@end
@implementation NSSet (MACollectionUtilities)
@@ -73,4 +85,9 @@ - (id)ma_match: (BOOL (^)(id obj))block
return nil;
}
+- (NSArray *)ma_sorted: (BOOL (^)(id a, id b))lessThan
+{
+ return [[self allObjects] ma_sorted: lessThan];
+}
+
@end
View
@@ -27,6 +27,7 @@ Methods are provided on `NSArray` and `NSSet` to do mapping, filtering, and matc
* `ma_select:` - Call the block once for each object in the collection. Use the objects where the block returns `YES` to create a new collection.
* `ma_match:` - Search for an object in the collection for which the block returns `YES` and return it.
* `ma_reduce:block:` - Start an accumulated value with the first argument. Call the block on each element of the array, passing it that element and the accumulated value so far. Set the accumulated value to the result. Allows an arbitrary "summation" operation to be performed on an array.
+* `ma_sorted:` - Use the block as a comparator to sort the array. Unlike the built-in Cocoa methods, the comparator returns a single `BOOL`, indicating whether the two objects should be sorted in ascending order. Note that this is different from the normal Cocoa technique of returning ascending, descending, or equal. Due to this difference, the comparator will be called somewhat more often than with the standard Cocoa methods, since it sometimes needs to be called twice to fully detect the ordering of a pair of objects.
Helper macros
@@ -37,6 +38,7 @@ To simplify the use of the above methods, helper macros are provided. These macr
* The `MAP`, `SELECT`, and `MATCH` macros all correspond to the methods of the same names.
* The `REJECT` macro is equivalent to a `SELECT` except that it selects objects for which the expression is *false*.
* The `REDUCE` macro takes three arguments: the collection, the initial value, and the expression to use for reduction. This macro implicitly creates parameters `a` (the accumulated value) and `b` (the object from the array).
+* The `SORTED` macro implicitly creates parameters `a` and `b`, and the second parameter should be an expression which evaluates to true if `a` should be sorted before `b`.
Examples
@@ -74,6 +76,10 @@ Sum all of the lengths of the strings in an array:
NSNumber *sumObj = REDUCE(stringArray, nil, [NSNumber numberWithInteger: [a integerValue] + [b length]]);
NSUInteger sum = [sumObj integerValue];
+Sort an array of strings ascending in order of string length:
+
+ NSArray *orderedArray = SORTED(array, [a length] < [b length]);
+
Parallel Enumeration
--------------------
View
12 main.m
@@ -135,6 +135,17 @@ static void TestReduce(void)
TEST_ASSERT([result isEqualToString: @"hello world"]);
}
+static void TestSorting(void)
+{
+ NSArray *array = ARRAY(@"one", @"three", @"four", @"eleven", @"seventeen");
+ NSArray *result = SORTED(array, [a length] > [b length]);
+ TEST_ASSERT([result isEqual: ARRAY(@"seventeen", @"eleven", @"three", @"four", @"one")]);
+
+ NSSet *set = SET(@"one", @"three", @"four", @"eleven", @"seventeen");
+ result = SORTED(set, [a length] > [b length]);
+ TEST_ASSERT([result isEqual: ARRAY(@"seventeen", @"eleven", @"three", @"four", @"one")]);
+}
+
int main(int argc, char **argv)
{
WithPool(^{
@@ -145,6 +156,7 @@ int main(int argc, char **argv)
TEST(TestSetMethods);
TEST(TestSetMacros);
TEST(TestReduce);
+ TEST(TestSorting);
NSString *message;
if(gFailureCount)

0 comments on commit 0f680db

Please sign in to comment.