NSSetに順番はない。しかし、Cocoaには順番のあるNSSetもあったりする。
それがNSOrderedSetである(OS10.7, iOS5以降で利用可)。
それって配列じゃないの?
という指摘はごもっとも。APIを眺めていても似たようなのが並んでいるし、積極的に使う理由も見えてはこない。
じゃあ、また性能を評価してみましょうということで、この前と同じコードで時間を計測してみる。
で、その結果(条件は以前と同じ. 10000個を登録、列挙、内包確認、取得)
NSArray | NSSet | NSOrderedSet | |
---|---|---|---|
追加 | 0.004542 | 0.0059005 | 0.014364 |
Fast Enumeration | 0.000060 | 0.0001296 | 0.000085 |
contains | 4.849716 | 0.0054603 | 0.045996 |
Indexアクセス | 0.001285 | x | 0.001117 |
・ 順番があるだけに、NSSetより全体的に遅い模様。Fast Enumerationは少し速いけど。
・ containsの処理はNSSetには及ばないものの、NSArrayよりはまだまだずっと速い。
ここまでの結果を踏まえ
NSArrayの代わりにNSOrderedSetを使いたくなったならそれで良し。
いやいや、別に無理して使うほどでもないでしょ。
という人向けにNSSetだけが持つ素敵な機能を紹介しよう。
それがこのメソッドの面々。
- (void)intersectSet:(NSSet *)other;
- (void)minusSet:(NSSet *)other;
- (void)unionSet:(NSSet *)other;
具体的な動作は以下を。
NSMutableOrderedSet *aSet = [NSMutableOrderedSet orderedSetWithArray:@[ @"apple", @"banana", @"cherry", @"durian" ]]; NSOrderedSet *bSet = [NSOrderedSet orderedSetWithArray:@[ @"cherry", @"fig", @"grape" ]]; [aSet intersectOrderedSet:bSet]; NSLog(@"intersect=%@", aSet);
出力: [ cherry ]
2つのSetから共通のものを抜き出してくれる。
NSMutableOrderedSet *aSet = [NSMutableOrderedSet orderedSetWithArray:@[ @"apple", @"banana", @"cherry", @"durian" ]]; NSOrderedSet *bSet = [NSOrderedSet orderedSetWithArray:@[ @"cherry", @"fig", @"grape" ]]; [aSet minusOrderedSet:bSet]; NSLog(@"minus=%@", aSet);
出力: [ apple, banana, durian ]
指定したSetが含む要素を削除する。
NSMutableOrderedSet *aSet = [NSMutableOrderedSet orderedSetWithArray:@[ @"apple", @"banana", @"cherry", @"durian" ]]; NSOrderedSet *bSet = [NSOrderedSet orderedSetWithArray:@[ @"cherry", @"fig", @"grape" ]]; [aSet unionOrderedSet:bSet]; NSLog(@"union=%@", aSet);
出力: [ apple, banana, cherry, durian, fig, grape ]
2つのSetを結合する(重複なし)。
NSArrayで実装するとちょっと面倒な処理も、
NSOrderedSet(NSMutableOrderedSet)ならこの通り。
NSArrayとNSOrderedSetの相互の変換もAPIが用意されているので自由自在。
ただし、NSSetは要素に同じオブジェクトは入れられない。
そういうNSArrayをNSOrderdSetにすると重複した要素は1つにまとめられる。
そこだけ注意しつつ、
適材適所で使い分けるときっと幸せになれる、はず。