在Objective C中随机化NSArray的规范方法

Geo*_*old 38 iphone random objective-c

有没有一种规范的方法可以在Objective C中随机化一个数组?

Bre*_*don 59

我的实用程序库在NSMutableArray上定义了这个类别:

@interface NSMutableArray (ArchUtils_Shuffle)
- (void)shuffle;
@end

// Chooses a random integer below n without bias.
// Computes m, a power of two slightly above n, and takes random() modulo m,
// then throws away the random number if it's between n and m.
// (More naive techniques, like taking random() modulo n, introduce a bias 
// towards smaller numbers in the range.)
static NSUInteger random_below(NSUInteger n) {
    NSUInteger m = 1;

    // Compute smallest power of two greater than n.
    // There's probably a faster solution than this loop, but bit-twiddling
    // isn't my specialty.
    do {
        m <<= 1;
    } while(m < n);

    NSUInteger ret;

    do {
        ret = random() % m;
    } while(ret >= n);

    return ret;
}

@implementation NSMutableArray (ArchUtils_Shuffle)

- (void)shuffle {
    // http://en.wikipedia.org/wiki/Knuth_shuffle

    for(NSUInteger i = [self count]; i > 1; i--) {
        NSUInteger j = random_below(i);
        [self exchangeObjectAtIndex:i-1 withObjectAtIndex:j];
    }
}

@end
Run Code Online (Sandbox Code Playgroud)

确保srandom(time(NULL))在调用之前的某个时间对随机数生成器(例如)进行播种; 否则输出不会很随机.

  • 如果您使用的是OSX 10.7或iOS 4.3或更高版本,则可以使用`arc4random_uniform(upper_bound)`而不必编写或使用`random_below(i)`函数. (12认同)
  • @bresc使用`srandom(time(NULL))`随机种子或使用`arc4random()`代替 (6认同)

Abr*_*odj 20

这里是!

- (NSArray*)shuffleArray:(NSArray*)array {

    NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:array];

    for(NSUInteger i = [array count]; i > 1; i--) {
        NSUInteger j = arc4random_uniform(i);
        [temp exchangeObjectAtIndex:i-1 withObjectAtIndex:j];
    }

    return [NSArray arrayWithArray:temp];
}
Run Code Online (Sandbox Code Playgroud)


Nat*_*ger 7

if ([array count] > 1) {
    for (NSUInteger shuffleIndex = [array count] - 1; shuffleIndex > 0; shuffleIndex--)
        [array exchangeObjectAtIndex:shuffleIndex withObjectAtIndex:random() % (shuffleIndex + 1)];
}
Run Code Online (Sandbox Code Playgroud)

确保使用srandomdev()或srandom()为random()函数设定种子.

  • 由于模数,此代码略有偏差; 有关详细信息,请参阅http://en.wikipedia.org/wiki/Fisher-Yates_shuffle#Modulo_bias. (2认同)