NSArrayを特定のindexを中心にsortする
例えば{ 1,2,3,4,5, }
で、添字4でセンタリングして{ 3,4,5,1,2, }
とか
添字3でセンタリングして{ 2,3,4,5,1, }
みたいなセンタリング。
- (NSArray *)_centering:(NSArray *)array current:(NSInteger)cur {
NSInteger count = array.count;
NSInteger half = (NSInteger)floor((CGFloat)count/2.f);
NSInteger limit = half;
NSRange zeroRange = NSMakeRange(0, 0);
NSRange behindRange = zeroRange;
NSRange wrapRange = zeroRange;
NSInteger len = limit+cur;
if (len>count) {
wrapRange = NSMakeRange(0, len-count);
limit = count-cur;
}
behindRange = NSMakeRange(cur, limit);
NSMutableArray *sorted = [NSMutableArray arrayWithArray:array];
NSArray *behind = [sorted subarrayWithRange:behindRange];
[sorted removeObjectsInRange:behindRange];
[sorted addObjectsFromArray:behind];
if (!NSEqualRanges(wrapRange, zeroRange)) {
NSArray *wrap = [sorted subarrayWithRange:wrapRange];
[sorted removeObjectsInRange:wrapRange];
[sorted addObjectsFromArray:wrap];
}
return sorted;
}
検証したら飽きてきたので読めばわかるレベルだしコメントは無い。
変数名は適当なので英語的には間違っているかもしれない。
本当はrangeを使わないで、enumeratorでindexが中心より大きいときと小さいときでreverseさせたりして並べ変えるとかも挑戦してみたけどNSMutableArrayでreplaceとか細かい処理が多くなるだけで思ったよりも早くなかったのでやめた。
見直したらイロイロひどかったのでカテゴリにした。
片手間じゃダメだな。
@interface NSArray (Sort)
/**
indexの値が配列の真ん中にくるよう並べ替えた配列を返す
{1,2,3}添字0で実行->{3,1,2,}となる。
配列の件数が偶数の場合は、{1,2,3,4,} 添字0で実行->{3,4,1,2,}となる。
**/
- (NSArray *)arrayWithCenteringIndex:(NSInteger)center;
@end
@implementation NSArray (Sort)
- (NSArray *)arrayWithCenteringIndex:(NSInteger)center {
if (center < 0 || center >= self.count) {
// 不正な値
return nil;
}
NSInteger count = self.count;
NSInteger half = (NSInteger)floor((CGFloat)count/2.f);
if (self.count <= 1 || center == half) {
// 配列が1件のときは計算の必要が無い
// centerが中心の場合も計算の必要が無い
return [NSArray arrayWithArray:self];
}
NSMutableArray *sorted = [NSMutableArray arrayWithArray:self];
NSRange behindRange = NSMakeRange(0, 0);
NSInteger length = 0;
if (center <= half) {
length = center + half +1;
}
else {
length = center - half;
}
behindRange = NSMakeRange(0, length);
NSArray *behind = [sorted subarrayWithRange:behindRange];
[sorted removeObjectsInRange:behindRange];
[sorted addObjectsFromArray:behind];
return sorted;
}
@end
これうまく動いてないな。。。