例。15個のオブジェクトを含む配列があります。与えられたインデックスから列挙を始めたい。インデックス5から始めて、次に上のインデックス、下のインデックス、上、下などと言います。ラップアラウンドしたくないのですが、停止して未踏の方向に進みます。
したがって、私の例のインデックスの順序は次のようになります。5、6、4、7、3、8、2、9、1、10、0、11、12、13、14
これはどのように行うことができますか?
例。15個のオブジェクトを含む配列があります。与えられたインデックスから列挙を始めたい。インデックス5から始めて、次に上のインデックス、下のインデックス、上、下などと言います。ラップアラウンドしたくないのですが、停止して未踏の方向に進みます。
したがって、私の例のインデックスの順序は次のようになります。5、6、4、7、3、8、2、9、1、10、0、11、12、13、14
これはどのように行うことができますか?
サブアレイを作成する必要のない、よりコンパクトな実装を次に示します。
@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
-(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
}
}
それは質問に答えますが、特にDRYではなく、サブアレイを作成すると、本来あるべきものよりも効率が低下します。
@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
この回答に対する@jalmaasのクレジット