2010-10-22 48 views
7

我正在嘗試使用objective-c塊實現二分搜索。我正在使用功能indexOfObject:inSortedRange:options:usingComparator:。這是一個例子。如何在內聯中編寫Objective-C塊?

// 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); 

回答

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); 
+0

您可以請將標題聲明添加到您的答案? – JJD 2011-01-21 09:21:18

+0

請更正圓括號的位置。它必須像這樣:NSComparisonResult(^ MakeComparisonBlock)(id,id)=(^(id lhs,id rhs){...});'。 SO不允許我編輯單個字符。 – JJD 2011-10-10 12:41:59

+0

@JJD其實,這些括號是不必要的。當從內聯轉換到全局時,我意外地將它們留在了原來的位置,而較老的編譯器也放棄了它。我會刪除它們。 – ughoavgfhw 2011-10-10 14:27:14

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); 

我非常相似的輸出到了原來實行與內塊定義方法調用。

+0

我真的很喜歡您的實現。雖然,因爲我不能給出2個正確答案,所以我必須決定@ ughoavgfhw,因爲我要求一個外部定義的Objective-C塊。別擔心! - 有趣的是,當我自動完成'[self compareNSNumber:id lhs]'時,Xcode添加了一個冒號和一個錯誤參數。 – JJD 2011-10-10 12:50:18