从givven索引search两种方式枚举NSArray(环绕)

例。 我有一个包含15个对象的数组。 我想从一个给定的索引开始枚举。 先从索引5开始,然后是上面的索引,下面的索引,上面的,下面的等等…我确实希望它包围。

所以在我的例子中索引的顺序是。 5,6,4,7,3,8,2,9,1,10,0,11,14,12,13

有一个类似于下面的行的方法签名会很棒,但是我不需要这个答案:

- (void)enumerateFromIndex:(NSUInteger)index wrapAroundAndGoBothWays:(void (^)(id obj, NSUInteger idx, BOOL *stop))block 

如何才能做到这一点? 想避免复制数组等

在这篇文章中,我们没有环绕它: 枚举NSArray从givven索引search两种方式(没有环绕)

从@omz借用,这是包装变体,这更简单:

 @implementation NSArray (Extensions) - (void)enumerateFromIndex:(NSUInteger)index wrapAroundAndGoBothWays:(void (^)(id obj, NSUInteger idx, BOOL *stop))block { BOOL stop = NO; NSUInteger actual = index; for (NSUInteger i = 0; i < self.count && !stop; i++) { actual += (2*(i%2)-1)*i; actual = (self.count + actual)%self.count; block([self objectAtIndex:actual], actual, &stop); } } @end 

这是一个math问题。 有一个很好的解决scheme。 但是,它涉及到事先对索引列表进行sorting。

这个想法是把从0到15的整数放在一个圆上,并把它们按照它们出现在一个轴上的顺序排列。

由于在ObjC中这样做是非常乏味的,我提出了python解决scheme:

 from math import pi, cos def circlesort(N, start): eps = 1e-8 res = range(N) def f(x): return -cos(2*pi*(x-start-eps)/N) res.sort( lambda x,y:cmp(f(x), f(y)) ) return res 

然后

 print circlesort(15, 5) 

输出

 [5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0, 11, 14, 12, 13] 

这是期望的结果。

编辑

好的,这是一个C实现:

 #include <stdlib.h> #include <math.h> #define sign(x) ((x)>0?1:(x)<0?-1:0) void circlesort(int* values, int N, int start){ double f(int x) { return -cos(2*M_PI*((double)(x-start)-.25)/N); } int compare (const void * a, const void * b) { return sign( f(*(int*)a) - f(*(int*)b) ); } qsort (values, N, sizeof(int), compare); } 

这将围绕一个长度为N的整数数组。使用它是这样的:

 int i, N = 15; int indexes[N]; for (i=0;i<N;i++) indexes[i] = i; circlesort(indexes, N, 5); 

现在数组indexes按照所需的顺序sorting。 因为有嵌套函数,所以应该在编译器标志中添加-fnested-functions

编辑2

考虑到有一个更简单的解决scheme(请参阅我的其他答案)这个事实是相当学术的。