2013年3月15日金曜日

独自クラスの配列をソートする

独自の型を持つ要素の配列をソートするには、NSArrayクラスの「sortedArrayUsingSelector」メソッドを使います。

例えば、TestClassという独自のクラスを配列にしてソートさせたい場合、以下のようにします。


@interface TestClass : NSObject {
@public
NSString *scale;
}

-(NSComparisonResult)compare_func:(TestClass*)a; // ソート時に呼ばれます

@property (nonatomic, retain) NSString *scale;

@end


@implementation TestClass
@synthesize scale;

-(id)init
{
self = [super init];
if (self) {
scale = @"ちゅうくらい";
}
return self;
}

-(id)initWithString:(NSString*)str
{
self = [super init];
if (self) {
scale = [str retain];
}
return self;
}

-(NSComparisonResult)compare_func:(TestClass*)a // ソート時に呼ばれます
{
if ([self.scale isEqualToString:@"ちゅうくらい"]) {
if ([a.scale isEqualToString:@"おおきい"]) {
return NSOrderedAscending;
} else if ([a.scale isEqualToString:@"ちゅうくらい"]) {
return NSOrderedSame;
} else {
return NSOrderedDescending;
}
} else if ([self.scale isEqualToString:@"おおきい"]) {
return NSOrderedDescending;
} else if ([self.scale isEqualToString:@"ちいさい"]) {
return NSOrderedAscending;
}
return NSOrderedAscending;
}

@end




ソート処理の中身とかは別にどうでも良いのですが、重要なのはソート処理に使うメソッドを用意しておくということです。
このクラスを配列にしてソートさせるには、以下のようにします。


// 独自クラス(TestClass)の配列を生成
NSArray *test_array = [[NSArray arrayWithObjects:
       [[[TestClass alloc] init] autorelease]
     , [[[TestClass alloc] initWithString:@"おおきい"] autorelease]
     , [[[TestClass alloc] initWithString:@"ちいさい"] autorelease]
     , nil] retain];

// ソート
NSArray *sorted_array = [test_array sortedArrayUsingSelector:@selector(compare_func:)];

// 結果を出力
for (TestClass *tc in sorted_array) {
    NSLog(@"%@", tc.scale);
}



NSArrayクラスの「sortedArrayUsingSelector」メソッドの引数に独自クラスに実装したソート用のメソッド(compare_func:)を指定することで、NSArrayがソート時に呼び出してくれるようになります。

結果は以下のようになります。


ちいさい
ちゅうくらい
おおきい






NSArrayクラスの「sortedArrayUsingSelector」メソッドは要素となるクラスにソート処理を実装しなければなりませんが、「sortedArrayUsingFunction」メソッドはソート処理を外部の関数に指定することができます。


// ソート処理を配列要素ではなく、外部の関数に定義
NSInteger compare_func(TestClass *a, TestClass *b, void* context)
{
if ([a.scale isEqualToString:@"ちゅうくらい"]) {
if ([b.scale isEqualToString:@"おおきい"]) {
return NSOrderedAscending;
} else if ([b.scale isEqualToString:@"ちゅうくらい"]) {
return NSOrderedSame;
} else {
return NSOrderedDescending;
}
} else if ([a.scale isEqualToString:@"おおきい"]) {
return NSOrderedDescending;
} else if ([a.scale isEqualToString:@"ちいさい"]) {
return NSOrderedAscending;
}
return NSOrderedAscending;
}


int main (int argc, const char * argv[])
{
NSArray *test_array = [[NSArray arrayWithObjects:[[[TestClass alloc] init] autorelease]
  , [[[TestClass alloc] initWithString:@"おおきい"] autorelease]
  , [[[TestClass alloc] initWithString:@"ちいさい"] autorelease]
  , nil] retain];
NSArray *sorted_array = [test_array sortedArrayUsingFunction:compare_func context:NULL];
for (TestClass *tc in sorted_array) {
NSLog(@"%@", tc.scale);
}
return 0;
}



結果は先の結果と同じになります。




0 件のコメント:

コメントを投稿