列挙なし
列挙せずにインデックスに手動でメモリを割り当て/解放することで、下位レベルで何かを行うことができます。これにより、ランダムなインデックスも表示されます。
NSIndexSet *_set = ... // your input index set
NSUInteger *_integerCArray = malloc(_set.count * sizeof(NSUInteger));
#if __LP64__
NSRange _indicesRange = NSMakeRange(0, UINT64_MAX);
#else
NSRange _indicesRange = NSMakeRange(0, UINT32_MAX);
#endif
[_set getIndexes:_integerCArray maxCount:_set.count inIndexRange:&_indicesRange];
NSInteger _randomIndex = _integerArray[arc4random_uniform((u_int32_t)_set.count)]; // the random index
free(_integerCArray), _integerCArray = nil;
列挙付き
列挙型に興味がないと言ったのは知っています。公平を期すために、それは実際には効率的な方法ではありませんが、必要に応じてランダムなインデックスを確実に提供し、読みやすく、メモリ管理がはるかに安全ですこの場合:
NSIndexSet *_set = ... // your input index set
__block NSInteger _counter = arc4random_uniform((u_int32_t)_set.count); // assume there are fewer indices in the set than UINT32_MAX
NSInteger _randomIndex = [_set indexPassingTest:^BOOL(NSUInteger idx, BOOL * _Nonnull stop) {
return --_counter < 0;
}];
O(n/2)
注:このアイデアは、オプションを使用しNSEnumerationReverse
てランダムカウンターがより大きい場合にも最適化できますが_set.count / 2
、セットが基本的に巨大な場合、この回答でそれを解決することについて心配しませんでした。何百ものインデックスがあるため、この不器用なソリューションでも問題なく使用できます。