1

我需要从包含在NSIndexSet.

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

如果没有,如何实施?

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

编辑:令我失望的是,不能保证从集合中返回随机对象的NSSet状态文档。-anyObject不幸的是NSIndexSet,关于实施-getIndexes:maxCount:inIndexRange:

4

2 回答 2

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

于 2016-01-12T12:55:33.047 回答
0

首先生成一个介于0和之间的随机数[indexSet count]-1

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

NSUInteger index = [indexSet firstIndex];

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

也看看这个问题

于 2016-01-12T12:07:11.597 回答