RailsのActiveRecordやC#のLINQではデータ列に対して選択や絞り込みなどを行う際、SelectやWhereなどを用いて要素を絞りこんだり要素のプロパティの集合を取り出したりできます。言い換えるとある集合に対する操作の結果として別の集合(または値)を取り出すための操作が用意されています。

Lispのような関数型言語のリスト操作のような感じもありますね。標準のRubyでいうとArray#mapとかArray#all?あたりがこれに該当します。

これと同じようなことをObjective-CのNSArrayに対して出来ないかなーと思って調べたところこんなライブラリが見つかりました。

ColinEberhardt/LinqToObjectiveC

このカテゴリを導入すると、NSArrayやNSDictionaryにlinq_wherelinq_selectなるメソッドが追加されます。

これ使いたいなーとおもった場面を、使い方の説明も兼ねて紹介します。

登場人物

こんな感じの役に立たないほげクラスがあったとしましょう。

 1typedef NS_ENUM(NSUInteger, HogeType){
 2    HogeFirst,
 3    HogeSecond
 4};
 5
 6@interface Hoge : NSObject
 7
 8@property HogeType type;
 9@property NSString *name;
10
11+ (id)hogeWithType:(HogeType)type;
12
13@end

準備

そして、次のように2種類のほげオブジェクトをたくさん保持する配列があるとします。

1- (void)doSomething
2{
3    NSMutableArray *array = [NSMutableArray new];
4    [array addObject:[Hoge hogeWithType:HogeFirst];
5    [array addObject:[Hoge hogeWithType:HogeSecond];
6    // このあとランダムに詰め込む
7}

HogeFirstのみの配列にしたい

いよいよlinq_whereの出番です。あなたはHogeFirstのみを集めた配列を用意したく。ループで愚直に書くとこうなります。

 1- (NSArray*)getHogeFirstArray
 2{
 3    // array にはランダムなHogeが入っている
 4    NSMutableArray *results = [NSMutableArray new];
 5
 6    for (Hoge *hoge in array) {
 7        if (hoge.type == HogeFirst) {
 8            [results addObject:hoge];
 9        }
10    }
11    return results;
12}

これに対しlinq_whereを使ったバージョンをこのようになります。

1- (NSArray*)getHogeFirstArray
2{
3    // array にはランダムなHogeが入っている
4    return [array linq_where:^BOOL(Hoge *hoge){
5        return hoge.type == HogeFirst;
6    }];
7}

さいごに

パフォーマンスはまだ調べていませんが、書き方としては少しスマートになった気がします。僕はこちらのほうが好み。

selectやwhere以外にもたくさんのメソッドが提供されているので試す価値あり、です。