セット内のオブジェクトのプロパティに基づいてNSSet
/NSMutableSet
内のオブジェクトをソートする最も効率的な方法は何ですか?今のところ、各オブジェクトを繰り返し処理し、NSMutableArray
に追加し、その配列をNSSortDescriptor
で並べ替えています。
使ってみて
[[mySet allObjects] sortedArrayUsingDescriptors:descriptors];
編集:iOS≥4.0およびMac OS X≥10.6では、直接使用できます
[mySet sortedArrayUsingDescriptors:descriptors];
オブジェクトのセットをソートする「最も効率的な方法」は、実際の意味によって異なります。偶然の仮定(前の回答で作成されたもの)は、セット内のオブジェクトの1回限りの並べ替えです。この場合、@ cobbalが提案するものと、あなたが思いついたものとの間のトスアップだと思います。おそらく次のようなものです。
NSMutableArray* array = [NSMutableArray arrayWithCapacity:[set count]];
for (id anObject in set)
[array addObject:anObject];
[array sortUsingDescriptors:descriptors];
(@cobbalのアプローチでは2つの自動解放された配列が作成されるため、トスアップだと言います。これにより、メモリフットプリントが2倍になります。
ただし、、セット内の要素を複数回ソートしている場合(特に通常の場合)、これは間違いなく効率的なアプローチではありません。 NSMutableArrayを保持し、NSSetとの同期を維持し、毎回-sortUsingDescriptors:を呼び出しますが、配列が既にソートされている場合でも、N個の比較が必要です。
Cocoa自体は、コレクションをソート順に維持するための効率的なアプローチを提供しません。 Javaには TreeSet クラスがあり、オブジェクトが挿入または削除されるたびに要素をソートされた順序で維持しますが、Cocoaはそうではありません。私自身の使用のために同様のものを開発します。
私が継承して改良したデータ構造フレームワークの一部として、 プロトコルとソートされたセットのいくつかの実装 を作成しました。具象サブクラスはいずれも、ソートされた順序で一連の個別のオブジェクトを保持します。まだ改善すべき点があります。最も重要なのは、-compare:(セット内の各オブジェクトが実装する必要がある)の結果に基づいてソートし、NSSortDescriptorをまだ受け入れないことです。 (回避策は、-compare:を実装して、オブジェクトの目的のプロパティを比較することです。)
考えられる欠点の1つは、これらのクラスが(現在)NS(Mutable)Setのサブクラスではないため、NSSetを渡す必要がある場合、順序付けされないことです。 (プロトコルにはNSSetを返す-setメソッドがあり、もちろん順序付けられていません。)フレームワークのNSMutableDictionaryサブクラスで行ったように、すぐに修正する予定です。フィードバックは大歓迎です。 :-)
IOS≥5.0およびMac OS X≥10.7の場合、NSOrderedSet
を直接使用できます
NSSetは、順序付けられていないオブジェクトのコレクションです。 Appleリファレンスを見る配列は順序付けられたコレクションです。
NSArrayを見ると、 http://developer.Apple.com/documentation/Cocoa/Conceptual/Collections/Articles/sortingFilteringArrays ... での並べ替えの例に関する議論があります。
リンクの例:
NSInteger alphabeticSort(id string1, id string2, void *reverse)
{
if (*(BOOL *)reverse == YES) {
return [string2 localizedCaseInsensitiveCompare:string1];
}
return [string1 localizedCaseInsensitiveCompare:string2];
}
// assuming anArray is array of unsorted strings
NSArray *sortedArray;
// sort using a selector
sortedArray =
[anArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
// sort using a function
BOOL reverseSort = NO;
sortedArray =
[anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort];
OS X 10.7およびiOS 5.0以降、NSOrderedSet
があります。これを使用して、オブジェクトをセットに保ち、順序を維持できます。 NSMutableOrderedSet
にはソートのメソッドがあります。ソートされたアイテムを保存するためにNSArray
のような個別のオブジェクトを作成する必要がないため、状況によってはパフォーマンスが向上する場合があります。
「sortedArrayUsingFunction:」はNSArrayとして結果を設定するため、NSSetをソートできません...そして、すべての上位ヒントは配列のみで機能します:)
NSArray *myArray = [mySet sortedArrayUsingDescriptors:descriptors];
完璧に動作し、他の方法は必要ありません:)