来自NSIndexSet的随机索引

时间:2016-01-12 11:21:12

标签: objective-c foundation nsindexset

我需要从NSIndexSet中包含的随机索引中选择一个随机索引。

作为参考,NSSet定义了从集合中挑选任意对象的-anyObject方法(documentation)。 NSIndexSet中是否有类似的功能?(事实证明-anyObject不能保证从集合中返回一个随机对象。)

如果没有,怎么可以实施?

注意:我找到了一个实现here,但它涉及对索引集元素的迭代。理想情况下,我想避免枚举。

修改:令我失望的是,NSSet的文档指出-anyObject无法保证从集合中返回随机对象。不幸的是,可以从NSIndexSet documentation, regarding the implementation of -getIndexes:maxCount:inIndexRange:

得出相同的结论

2 个答案:

答案 0 :(得分:0)

首先在0[indexSet count]-1之间生成一个随机数。

现在从indexSet获取randomNum索引处的索引。这样没有indexAtIndex:方法,但是这段代码会给你一个类似的结果:

NSUInteger index = [indexSet firstIndex];

for (NSUInteger i = 0, target = randomNum; i < target; i++)
  index = [indexSet indexGreaterThanIndex:index];

另请查看this question

答案 1 :(得分:0)

没有枚举

你可以在较低的层面做一些事情,为索引手动分配/释放一些内存而不进行任何枚举,这也提供了随机索引:

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优化此提示,但我不担心在这个答案,如果这个集合基本上是巨大的,这可能是一个好主意,但有几百个索引,你甚至不会麻烦使用这个笨拙的解决方案。

相关问题