Is there a canonical way to randomize an array in Objective C?
+2
A:
There is none built into the SDK if that's what you are asking.
You can use just about any randomization or shuffling algorithm you want however. Different algorithms have different tradeoffs in terms of randomness, efficiency, etc.
http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms
For algorithms that shuffle "in-place" start with a mutable array use
insertObject:atIndex:
removeObjectAtIndex:
For algorithms that reconstruct the array, feed it the original and build a new array.
Kailoa Kadano
2009-04-26 17:25:08
+2
A:
if ([array count] > 1) {
for (NSUInteger shuffleIndex = [array count] - 1; shuffleIndex > 0; shuffleIndex--)
[array exchangeObjectAtIndex:shuffleIndex withObjectAtIndex:random() % (shuffleIndex + 1)];
}
Make sure to seed the random() function with either srandomdev() or srandom().
Nathan Kinsinger
2009-04-26 18:34:39
What you wrote doesn't make sense as an instance method. As the code exists, it should just be a function or class method. Idiomatically, it should be an NSArray instance method that returns a new, shuffled array or an NSMutableArray instance method that shuffles itself.
Chuck
2009-04-26 18:41:40
True, I was just demonstrating the code here, wasn't really worried about putting it in a category. I also forgot to mention to seed the random() function with srandomdev() or srandom().
Nathan Kinsinger
2009-04-26 19:24:24
This code is slightly biased due to the modulo; see http://en.wikipedia.org/wiki/Fisher-Yates_shuffle#Modulo_bias for more about this.
Brent Royal-Gordon
2009-04-26 22:36:07
+18
A:
My utility library defines this category on NSMutableArray to do it:
@interface NSMutableArray (ArchUtils_Shuffle)
- (void)shuffle;
@end
// Unbiased random rounding thingy.
static NSUInteger random_below(NSUInteger n) {
NSUInteger m = 1;
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
Brent Royal-Gordon
2009-04-26 22:39:46