7

我正在尝试使用objective-c 块实现二进制搜索。我正在使用该功能indexOfObject:inSortedRange:options:usingComparator:。这是一个例子。

// A pile of data.
NSUInteger amount = 900000;
// A number to search for.
NSNumber* number = [NSNumber numberWithInt:724242];

// Create some array.
NSMutableArray* array = [NSMutableArray arrayWithCapacity:amount];
for (NSUInteger i = 0; i < amount; ++i) {;
    [array addObject:[NSNumber numberWithUnsignedInteger:i]];
}
NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];

// Run binary search.
int index1 = [array indexOfObject:number 
                    inSortedRange:NSMakeRange(0, [array count]) 
                          options:NSBinarySearchingFirstEqual 
                  usingComparator:^(id lhs, id rhs) {
                      if ([lhs intValue] < [rhs intValue]) {
                          return (NSComparisonResult)NSOrderedAscending;
                      } else if([lhs intValue] > [rhs intValue]) {
                          return (NSComparisonResult)NSOrderedDescending;
                      }
                      return (NSComparisonResult)NSOrderedSame;
                  }]; 
NSTimeInterval stop1 = [NSDate timeIntervalSinceReferenceDate]; 
NSLog(@"Binary: Found index position: %d in %f seconds.", index1, stop1 - start);

// Run normal search.
int index2 = [array indexOfObject:number];
NSTimeInterval stop2 = [NSDate timeIntervalSinceReferenceDate];
NSLog(@"Normal: Found index position: %d in %f seconds.", index2, stop2 - start);   

我想知道如何将外部定义的 Objective-c 块与上述功能一起使用。这里有两个比较函数。

NSComparisonResult compareNSNumber(id lhs, id rhs) {
    return [lhs intValue] < [rhs intValue] ? NSOrderedAscending : [lhs intValue] > [rhs intValue] ? NSOrderedDescending : NSOrderedSame;
}
NSComparisonResult compareInt(int lhs, int rhs) {
    return lhs < rhs ? NSOrderedAscending : lhs > rhs ? NSOrderedDescending : NSOrderedSame;
}

这些是参考以下声明编写的,这些声明可以在NSObjCRuntime.h.

enum _NSComparisonResult {NSOrderedAscending = -1, NSOrderedSame, NSOrderedDescending};
typedef NSInteger NSComparisonResult;
typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);
4

2 回答 2

21

您可以将块定义为全局变量,以获得类似于函数的效果。

NSComparisonResult (^globalBlock)(id,id) = ^(id lhs, id rhs) {
    if([lhs intValue] < [rhs intValue]) {
        return (NSComparisonResult)NSOrderedAscending;
    } else if([lhs intValue] > [rhs intValue]) {
        return (NSComparisonResult)NSOrderedDescending;
    }
    return (NSComparisonResult)NSOrderedSame;
};

然后,在进行比较的方法中:

int index1 = [array indexOfObject:number 
                    inSortedRange:NSMakeRange(0, [array count]) 
                          options:NSBinarySearchingFirstEqual 
                  usingComparator:globalBlock]; 

要将块放在标题中,供外部使用:

NSComparisonResult (^globalBlock)(id,id);
于 2011-01-17T03:36:25.697 回答
2

我知道这很旧,但我刚刚遇到它,我一直在尝试处理我的积木 foo,所以这里......

我创建了一个将您的 NSComparator 作为块返回的方法。它看起来像这样:

-(NSComparisonResult (^) (id lhs, id rhs))compareNSNumber{

return [[^(id lhs, id rhs)
         {
             return [lhs intValue] < [rhs intValue] ? (NSComparisonResult)NSOrderedAscending : [lhs intValue] > [rhs intValue] ? (NSComparisonResult)NSOrderedDescending : (NSComparisonResult)NSOrderedSame;

         } copy ] autorelease];
}

然后,我可以通过将二进制搜索执行更改为:

// Run binary search.
int index1 = [array indexOfObject:number 
                    inSortedRange:NSMakeRange(0, [array count]) 
                          options:NSBinarySearchingFirstEqual 
                  usingComparator:[self compareNSNumber]];
NSTimeInterval stop1 = [NSDate timeIntervalSinceReferenceDate]; 
NSLog(@"Binary: Found index position: %d in %f seconds.", index1, stop1 - start);

通过方法调用中的块定义,我得到了与原始实现非常相似的输出。

于 2011-01-17T02:06:37.750 回答