NSArrayとNSOrderedSet

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つにまとめられる。

 

そこだけ注意しつつ、

適材適所で使い分けるときっと幸せになれる、はず。