2013-01-15 13 views
8

Przykład. Mam tablicę z 15 obiektami. Chcę rozpocząć wyliczanie z danego indeksu. Powiedz początek od indeksu 5, a następnie do indeksu powyżej, do indeksu poniżej, powyżej, poniżej itd. Nie chcę, żeby się zawijał, ale raczej zatrzymał się i kontynuował w niezbadanym kierunku.Wylicz NSArray, rozpoczynając od przeszukiwanego indeksu, przeszukując oba sposoby (bez oblewania)

Tak więc kolejność indeksów w moim przykładzie byłaby. 5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0, 11, 12, 13, 14

Jak można tego dokonać?

+1

Czy chcesz go "wrap around" końce tablicy lub zatrzymać i kontynuować w niezbadanym kierunku? –

+0

Pytanie Goood! Dla mnie mogę myśleć tylko o użyciu tego ostatniego (zatrzymaj się i kontynuuj w niezbadanym kierunku), ale oczywiście byłby też drugi. Może otworzę sobie inne pytanie. – hfossli

+0

Zrobiłem własny post dla wrap wokół: http://stackoverflow.com/q/14354514/202451 – hfossli

Odpowiedz

7

Oto bardziej kompaktowy realizacja, która nie wymaga tworzenia subarrays:

@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

Świetna odpowiedź! Zdałem testy jednostkowe! – hfossli

0

Odpowiada na pytanie, ale nie jest szczególnie SUCHY, a tworzenie podbarw sprawia, że ​​jest on mniej wydajny niż powinien.

@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 

kuponów do @jalmaas dla tej odpowiedzi

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 

    } 
}