2010-10-22 18 views
7

Estoy tratando de implementar una búsqueda binaria usando bloques objetivo-c. Estoy usando la función indexOfObject:inSortedRange:options:usingComparator:. Aquí hay un ejemplo.Cómo escribir bloques Objective-C en línea?

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

Me pregunto cómo puedo usar un bloque object-c definido externamente con la función antes mencionada. Aquí hay dos funciones de comparación.

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

Aquellos están escritos en referencia a las siguientes declaraciones que se pueden encontrar en NSObjCRuntime.h.

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

Respuesta

21

Puede definir un bloque como una variable global para obtener un efecto similar a las funciones.

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

Luego, en el método de hacer la comparación:

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

Para poner el bloque en una cabecera, para uso externo:

NSComparisonResult (^globalBlock)(id,id); 
+0

¿Puede agregar la declaración del encabezado a su respuesta? – JJD

+0

Corrija la posición de la abrazadera redonda. Tiene que ser así 'NSComparisonResult (^ MakeComparisonBlock) (id, id) = (^ (id lhs, id rhs) {...});'. SO no me permite editar un solo personaje. – JJD

+0

@JJD En realidad, esos paréntesis son innecesarios. Accidentalmente los dejé cuando convertí de en línea a global, y los compiladores más antiguos lo dejan pasar. Los eliminaré. – ughoavgfhw

2

Sé que esto es viejo, pero me acaba de ejecutar a través de ella y yo he estado tratando de trabajar en mis bloques Foo, así que aquí va ...

He creado un método que devuelve su NSComparator como un bloque. Se ve así:

-(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]; 
} 

Yo era entonces capaz de ejecutar su código de ejemplo cambiando la ejecución búsqueda binaria para:

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

llegué salida muy similar a la aplicación original con la definición de bloque dentro de la llamada al método.

+0

me gusta mucho su aplicación. Sin embargo, dado que no puedo otorgar 2 respuestas correctas, tengo que decidir sobre @ ughoavgfhw porque solicité un bloque objetivo-c definido externamente. ¡Sin preocupaciones! - Curiosamente, Xcode agrega dos puntos y un argumento de error cuando autocompleto '[self compareNSNumber: id lhs]'. – JJD

Cuestiones relacionadas