在NSArray中挑选随机对象

Jos*_*hua 82 cocoa objective-c

假设我有一个包含对象的数组,1,2,3和4. 我如何从这个数组中选择一个随机对象?

Dav*_*ong 190

@Darryl的答案是正确的,但可以使用一些小调整:

NSUInteger randomIndex = arc4random() % theArray.count;
Run Code Online (Sandbox Code Playgroud)

修改:

  • 使用arc4random()over rand()并且random()更简单,因为它不需要播种(调用srand()srandom()).
  • 模运算符(%)使得整体更短的语句,同时也使得它在语义上更清晰.

  • "theArray.count是错误的.它可以工作,但是在NSArray上没有将count声明为@property,因此不应该通过点语法调用." ---这是不正确的.Dot语法和声明的属性实际上并不相关:您可以在无参数方法上使用点语法,完全没有问题. (43认同)
  • 从arc4random手册页:arc4random_uniform()建议使用像``arc4random()%upper_bound''这样的结构,因为当上限不是2的幂时,它避免了"模偏差". (27认同)
  • 请注意,RC4/ARC4不能提供统一的输出. (2认同)

fun*_*oll 17

这是我能想到的最简单的解决方案:

id object = array.count == 0 ? nil : array[arc4random_uniform(array.count)];
Run Code Online (Sandbox Code Playgroud)

这是必要的检查count,因为非nil却空无一人NSArray将返回0count,和arc4random_uniform(0)回报0.所以没有检查,你将超出阵列的界限.

这个解决方案很诱人但是错误,因为它会导致空数组崩溃:

id object = array[arc4random_uniform(array.count)];
Run Code Online (Sandbox Code Playgroud)

供参考,这是文档:

u_int32_t
arc4random_uniform(u_int32_t upper_bound);

arc4random_uniform() will return a uniformly distributed random number less than upper_bound.
Run Code Online (Sandbox Code Playgroud)

手册页没有提到传递时的arc4random_uniform返回值.00upper_bound

此外,arc4random_uniform已定义<stdlib.h>,但#import在我的iOS测试程序中添加不是必需的.


Dar*_*mas 11

也许是这样的:

NSUInteger randomIndex = (NSUInteger)floor(random()/RAND_MAX * [theArray count]);
Run Code Online (Sandbox Code Playgroud)

不要忘记初始化随机数生成器(例如srandomdev()).

注意:根据下面的答案,我已更新为使用-count而不是点语法.


Ale*_*kiy 9

@interface NSArray<ObjectType>  (Random)
- (nullable ObjectType)randomObject;
@end

@implementation NSArray (Random)

- (nullable id)randomObject
{
    id randomObject = [self count] ? self[arc4random_uniform((u_int32_t)[self count])] : nil;
    return randomObject;
}

@end
Run Code Online (Sandbox Code Playgroud)

编辑:更新了Xcode 7.泛型,可空性