Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chakrit/3889128 to your computer and use it in GitHub Desktop.
Save chakrit/3889128 to your computer and use it in GitHub Desktop.
NSOrderedSet for BlocksKit
Pod::Spec.new do |s|
s.name = 'BlocksKit+NSOrderedSet'
s.version = '1.0.0'
s.license = 'MIT'
s.summary = 'The NSOrderedSet block utilities you always wish you had.'
s.homepage = 'https://github.com/zwaldowski/BlocksKit'
s.author = { 'Zachary Waldowski' => 'zwaldowski@gmail.com' }
s.source = { :git => 'git://gist.github.com/1959168.git', :tag => 'origin/master' }
s.source_files = '*.{h,m}'
s.dependency 'BlocksKit'
end
//
// NSMutableOrderedSet+BlocksKit.h
// %PROJECT
//
#import "BKGlobals.h"
/** Block extensions for NSMutableOrderedSet.
These utilities expound upon the BlocksKit additions
to the immutable superclass by allowing certain utilities
to work on an instance of the mutable class, saving memory
by not creating an immutable copy of the results.
Includes code by the following:
- Zach Waldowski. <https://github.com/zwaldowski>. 2012. MIT.
@warning NSMutableOrderedSet is only available on iOS 5.0, OS X 10.7, or later.
@see NSOrderedSet(BlocksKit)
*/
@interface NSMutableOrderedSet (BlocksKit)
/** Filters a mutable ordered set to the objects matching the block.
@param block A single-argument, BOOL-returning code block.
@see reject:
*/
- (void)performSelect:(BKValidationBlock)block;
/** Filters a mutable ordered set to all objects but the ones matching the block,
the logical inverse to select:.
@param block A single-argument, BOOL-returning code block.
@see select:
*/
- (void)performReject:(BKValidationBlock)block;
/** Transform the objects in the set to the results of the block.
This is sometimes referred to as a transform, mutating one of each object:
[controllers map:^id(id obj) {
return [obj view];
}];
@param block A single-argument, object-returning code block.
*/
- (void)performMap:(BKTransformBlock)block;
@end
//
// NSMutableOrderedSet+BlocksKit.m
// BlocksKit
//
#import "NSMutableOrderedSet+BlocksKit.h"
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0
@implementation NSMutableOrderedSet (BlocksKit)
- (void)performSelect:(BKValidationBlock)block {
NSParameterAssert(block != nil);
NSIndexSet *list = [self indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return !block(obj);
}];
if (!list.count)
return;
[self removeObjectsAtIndexes:list];
}
- (void)performReject:(BKValidationBlock)block {
[self performSelect:^BOOL(id obj) {
return !block(obj);
}];
}
- (void)performMap:(BKTransformBlock)block {
NSParameterAssert(block != nil);
NSMutableArray *new = [NSMutableArray arrayWithCapacity:self.count];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id value = block(obj);
if (!value)
value = [NSNull null];
[new addObject:value];
}];
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.count)];
[self replaceObjectsAtIndexes:indexes withObjects:new];
}
@end
#endif
//
// NSOrderedSet+BlocksKit.h
// %PROJECT
//
#import "BKGlobals.h"
/** Block extensions for NSOrderedSet.
Both inspired by and resembling Smalltalk syntax, these utilities
allows for iteration of an ordered set in a concise way that
saves quite a bit of boilerplate code for filtering or finding
objects or an object.
Includes code by the following:
- Zach Waldowski. <https://github.com/zwaldowski>. 2012. MIT.
@warning NSOrderedSet is only available on iOS 5.0, OS X 10.7, or later.
@see NSArray(BlocksKit)
@see NSSet(BlocksKit)
*/
@interface NSOrderedSet (BlocksKit)
/** Loops through an ordered set and executes the given block with each object.
@param block A single-argument, void-returning code block.
*/
- (void)each:(BKSenderBlock)block;
/** Enumerates through an ordered set concurrently and executes
the given block once for each object.
Enumeration will occur on appropriate background queues. This
will have a noticeable speed increase, especially on dual-core
devices, but you *must* be aware of the thread safety of the
objects you message from within the block.
@param block A single-argument, void-returning code block.
*/
- (void)apply:(BKSenderBlock)block;
/** Loops through an ordered set to find the object matching the block.
match: is functionally identical to select:, but will stop and return
on the first match.
@param block A single-argument, BOOL-returning code block.
@return Returns the object if found, `nil` otherwise.
@see select:
*/
- (id)match:(BKValidationBlock)block;
/** Loops through an ordered set to find the objects matching the block.
@param block A single-argument, BOOL-returning code block.
@return Returns an ordered set of the objects found, `nil` otherwise.
@see match:
*/
- (NSOrderedSet *)select:(BKValidationBlock)block;
/** Loops through an ordered set to find the objects not matching the block.
This selector performs *literally* the exact same function as select, but in reverse.
This is useful, as one may expect, for removing objects from an ordered set:
NSOrderedSet *new = [bookmarks reject:^BOOL(id obj) {
return ([obj isLoading]);
}];
@param block A single-argument, BOOL-returning code block.
@return Returns an ordered set of all objects not found, `nil` if all are excluded.
*/
- (NSOrderedSet *)reject:(BKValidationBlock)block;
/** Call the block once for each object and create an ordered set of the return values.
This is sometimes referred to as a transform, mutating one of each object:
NSOrderedSet *new = [mimeTypes map:^id(id obj) {
return [@"x-company-" stringByAppendingString:obj]);
}];
@param block A single-argument, object-returning code block.
@return Returns an ordered set of the objects returned by the block.
*/
- (NSOrderedSet *)map:(BKTransformBlock)block;
/** Arbitrarily accumulate objects using a block.
The concept of this selector is difficult to illustrate in words. The sum can
be any NSObject, including (but not limited to) an NSString, NSNumber, or NSValue.
You can also do something like summing the count of an item:
NSNumber *sum = [bodyList reduce:nil withBlock:^id(id sum, id obj) {
return [NSNumber numberWithInteger: [sum integerValue] + obj.numberOfAppendages];
}];
NSUInteger numberOfBodyParts = [sum integerValue];
@param initial The value of the reduction at its start.
@param block A block that takes the current sum and the next object to return the new sum.
@return An accumulated value.
*/
- (id)reduce:(id)initial withBlock:(BKAccumulationBlock)block;
/** Loops through an ordered set to find whether any object matches the block.
This method is similar to the Scala list `exists`. It is functionally
identical to match: but returns a `BOOL` instead. It is not recommended
to use any: as a check condition before executing match:, since it would
require two loops through the ordered set.
@param block A single-argument, BOOL-returning code block.
@return YES for the first time the block returns YES for an object, NO otherwise.
*/
- (BOOL)any:(BKValidationBlock)block;
/** Loops through an ordered set to find whether no objects match the block.
This selector performs *literally* the exact same function as all: but in reverse.
@param block A single-argument, BOOL-returning code block.
@return YES if the block returns NO for all objects in the ordered set, NO otherwise.
*/
- (BOOL)none:(BKValidationBlock)block;
/** Loops through an ordered set to find whether all objects match the block.
@param block A single-argument, BOOL-returning code block.
@return YES if the block returns YES for all objects in the ordered set, NO otherwise.
*/
- (BOOL)all:(BKValidationBlock)block;
/** Tests whether every element of this ordered set relates to the corresponding
element of another ordered set according to the block.
@param block A two-argument, BOOL-returning code block.
@return YES if every element relates to the corresponding element in the other collection, NO otherwise.
*/
- (BOOL)corresponds:(NSOrderedSet *)list withBlock:(BKKeyValueValidationBlock)block;
@end
//
// NSOrderedSet+BlocksKit.m
// BlocksKit
//
#import "NSOrderedSet+BlocksKit.h"
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0
@implementation NSOrderedSet (BlocksKit)
- (void)each:(BKSenderBlock)block {
NSParameterAssert(block != nil);
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
block(obj);
}];
}
- (void)apply:(BKSenderBlock)block {
NSParameterAssert(block != nil);
[self enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
block(obj);
}];
}
- (id)match:(BKValidationBlock)block {
NSParameterAssert(block != nil);
NSUInteger index = [self indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return block(obj);
}];
if (index == NSNotFound)
return nil;
return [self objectAtIndex:index];
}
- (NSOrderedSet *)select:(BKValidationBlock)block {
NSParameterAssert(block != nil);
NSArray *objects = [self objectsAtIndexes:[self indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return block(obj);
}]];
if (!objects.count)
return nil;
return [[self class] orderedSetWithArray:objects];
}
- (NSOrderedSet *)reject:(BKValidationBlock)block {
return [self select:^BOOL(id obj) {
return !block(obj);
}];
}
- (NSOrderedSet *)map:(BKTransformBlock)block {
NSParameterAssert(block != nil);
NSMutableOrderedSet *result = [NSMutableOrderedSet orderedSetWithCapacity:self.count];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id value = block(obj);
if (!value)
value = [NSNull null];
[result addObject:value];
}];
return result;
}
- (id)reduce:(id)initial withBlock:(BKAccumulationBlock)block {
NSParameterAssert(block != nil);
__block id result = [initial retain];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id new = block(result, obj);
[result release];
result = [new retain];
}];
return [result autorelease];
}
- (BOOL)any:(BKValidationBlock)block {
return [self match: block] != nil;
}
- (BOOL)none:(BKValidationBlock)block {
return [self match: block] == nil;
}
- (BOOL)all:(BKValidationBlock)block {
NSParameterAssert(block != nil);
__block BOOL result = YES;
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (!block(obj)) {
result = NO;
*stop = YES;
}
}];
return result;
}
- (BOOL)corresponds:(NSOrderedSet *)list withBlock:(BKKeyValueValidationBlock)block {
NSParameterAssert(block != nil);
__block BOOL result = NO;
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx < [list count]) {
id obj2 = [list objectAtIndex: idx];
result = block(obj, obj2);
} else {
result = NO;
}
*stop = !result;
}];
return result;
}
@end
BK_MAKE_CATEGORY_LOADABLE(NSOrderedSet_BlocksKit)
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment