规范的方式来随机化目标C中的一个NSArray

是否有一个规范的方式随机化Objective C中的数组?

我的实用程序库在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 

确保你在调用它之前的某个srandom(time(NULL))给随机数生成器(例如srandom(time(NULL))srandom(time(NULL)) ; 否则输出将不会很随机。

这里是!

 - (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]; } 
 if ([array count] > 1) { for (NSUInteger shuffleIndex = [array count] - 1; shuffleIndex > 0; shuffleIndex--) [array exchangeObjectAtIndex:shuffleIndex withObjectAtIndex:random() % (shuffleIndex + 1)]; } 

确保使用srandomdev()或srandom()对random()函数进行播种。

如果这就是你所要求的,没有内置到SDK中。

你可以使用任何你想要的随机化或混洗algorithm。 不同的algorithm在随机性,效率等方面有不同的权衡。

http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms

对于“就地”洗牌的algorithm,从可变数组使用开始

 insertObject:atIndex: removeObjectAtIndex: 

对于重新构build数组的algorithm,请提供原始数据并构build一个新数组。

我的解决scheme是一个类别的方法,返回一个数组的副本(autoreleased)与元素随机化(使用arc4random)。

 @interface NSArray (CMRandomised) /* Returns a copy of the array with elements re-ordered randomly */ - (NSArray *)randomised; @end /* Returns a random integer number between low and high inclusive */ static inline int randomInt(int low, int high) { return (arc4random() % (high-low+1)) + low; } @implementation NSArray (CMRandomised) - (NSArray *)randomised { NSMutableArray *randomised = [NSMutableArray arrayWithCapacity:[self count]]; for (id object in self) { NSUInteger index = randomInt(0, [randomised count]); [randomised insertObject:object atIndex:index]; } return randomised; } @end 

没有一个规范的方式没有在NSArray (即有一个像arrayWithRandomizedIndices的实例方法)或NSMutableArray (即有一个像randomizeIndices方法)的类别。

下面是我的库中的一个例子,它是NSMutableArray类别的一部分。 它会随机地重新排列数组,而不是随机地重排一些条目。

 - (void) randomizeIndices { if (self == nil || [self count] <= 1) { return; } int count = [self count]; NSMutableArray* copySelf = [NSMutableArray arrayWithArray:self]; NSMutableArray* mutableResultArray = [NSMutableArray alloc]; mutableResultArray = [mutableResultArray initWithCapacity:count]; [mutableResultArray autorelease]; int objectsMovedCount = 0; for (int i = 0; i < count; i++) { int index = rand() % (count - objectsMovedCount); id anObject = [copySelf objectAtIndex:index]; [mutableResultArray addObject:anObject]; [copySelf removeObjectAtIndex:index]; objectsMovedCount++; } [self setArray:mutableResultArray]; } 

调用srand(time(0)); 或者在调用这个方法之前或在方法的早期。

NSArray随机化为Objective-C类别方法:

 @implementation NSArray (NGDataDynamics) - (NSArray *)jumbled { NSMutableArray *jumbled = self.mutableCopy; NSUInteger idx = self.count-1; while(idx) { [jumbled exchangeObjectAtIndex:idx withObjectAtIndex:arc4random_uniform(idx)]; idx--; } return jumbled; } @end 

如所见: NSArray随机化和Psychedelia