2013-01-15 6 views
8

Esempio. Ho una matrice con 15 oggetti. Voglio iniziare a elencare da un dato indice. Supponiamo di iniziare dall'indice 5 e poi dall'indice sopra, dall'indice sotto, sopra, sotto ecc ... Non voglio che si avvolga, ma piuttosto si fermi e continui in direzione inesplorata.Enumerazione di NSArray a partire dall'indice di givven per la ricerca in entrambi i modi (no wrap around)

Quindi l'ordine degli indici nel mio esempio sarebbe. 5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0, 11, 12, 13, 14

Come si può fare?

+1

vuoi che a "wrap around", il estremità dell'array, o fermarsi e continuare nella direzione inesplorata? –

+0

Domanda giusta! Per quanto mi riguarda, posso solo pensare di usare quest'ultimo (fermarsi e continuare in direzione inesplorata), ma ovviamente ci sarebbe anche l'uso dell'altro. Forse aprirò un'altra domanda per questo. – hfossli

+0

Ho creato un proprio post per il wrap around: http://stackoverflow.com/q/14354514/202451 – hfossli

risposta

7

Ecco un'implementazione più compatto che non richiede la creazione di sottoarray:

@implementation NSArray (Extensions) 

- (void)enumerateFromIndex:(NSUInteger)index goBothWaysUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block 
{ 
    BOOL stop = NO; 
    for (NSUInteger i = 0; i < self.count && !stop; i++) { 
     if (index + i < self.count) { 
      block([self objectAtIndex:index + i], index + i, &stop); 
     } 
     if (i != 0 && !stop && i <= index) { 
      block([self objectAtIndex:index - i], index - i, &stop); 
     } 
    } 
} 

@end 
+0

Ottima risposta! Ha superato i miei test unitari! – hfossli

0

Risponde alla domanda, ma non è particolarmente ASCIUTTA e la creazione di sottotitoli lo rende meno efficiente di quello che dovrebbe essere.

@implementation NSArray (Extensions) 

- (void)enumerateFromIndex:(NSUInteger)index goBothWaysUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block 
{ 
    NSArray *lastObjects = [self subarrayFromIndex:index]; 
    NSArray *firstObjects = [self subarrayToIndex:index]; 
    int currentIndex = 0; 

    NSEnumerator *firstObjectsEnumerator = [firstObjects reverseObjectEnumerator]; 
    NSEnumerator *lastObjectsEnumerator = [lastObjects objectEnumerator]; 
    BOOL shouldStop = NO; 
    NSUInteger numberOfIndexesEnumerated = 0; 
    id obj = nil; 

    while(numberOfIndexesEnumerated < self.count) 
    { 
     if (obj = [lastObjectsEnumerator nextObject]) 
     { 
      NSInteger objIndex = [self indexOfObject:obj]; 
      block(obj, objIndex, &shouldStop); 
      currentIndex++; 
      numberOfIndexesEnumerated++; 
     } 
     if (shouldStop) 
     { 
      return; 
     } 

     if (obj = [firstObjectsEnumerator nextObject]) 
     { 
      NSInteger objIndex = [self indexOfObject:obj]; 
      block(obj, objIndex, &shouldStop); 
      currentIndex++; 
      numberOfIndexesEnumerated++; 
     } 
     if (shouldStop) 
     { 
      return; 
     } 
    } 
} 

@end 

crediti verso @jalmaas per questa risposta

1
-(void)enumerateArray:(NSArray *)array inBothDirectionsFromIndex:(int)startIndex 
{ 
    for (int i=0; i<array.count; i++) 
    { 
     int index = startIndex; 
     int indexAfter = startIndex + round(i/2.f) + (i%2 ? 0 : 1); 
     int indexBefore = startIndex - round(i/2.f); 

     if ((i%2 && indexAfter < array.count) || indexBefore < 0) 
     { 
      index = indexAfter; 
      if (indexBefore < 0) 
       index -= indexBefore + 1; 
     } 
     else if ((i > 0 && indexBefore > -1) || indexAfter > array.count-1) 
     { 
      index = indexBefore; 
      if (indexAfter > array.count-1) 
       index -= indexAfter - array.count;; 
     } 

     id item = [array objectAtIndex:index]; 

     //Do what you want with the item here 

    } 
} 
Problemi correlati