Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

canonical way to randomize an NSArray in Objective-C

Is there a canonical way to randomize an array in Objective-C?

like image 427
George Armhold Avatar asked Apr 26 '09 17:04

George Armhold


People also ask

How do you declare NSArray in Objective C?

In Objective-C, the compiler generates code that makes an underlying call to the init(objects:count:) method. id objects[] = { someObject, @"Hello, World!", @42 }; NSUInteger count = sizeof(objects) / sizeof(id); NSArray *array = [NSArray arrayWithObjects:objects count:count];

Can NSArray contain nil?

arrays can't contain nil.

How do you reverse an NSArray?

You can reverse a NSArray by writing your own loop iterating from the end towards the beginning and using a second array to add the items in reverse order. Or you can simply use - (NSEnumerator *)reverseObjectEnumerator from the NSArray class.

What is NSArray?

NSArray is an immutable Objective C class, therefore it is a reference type in Swift and it is bridged to Array<AnyObject> . NSMutableArray is the mutable subclass of NSArray .


1 Answers

My utility library defines this category on NSMutableArray to do it:

@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 

Make sure you seed the random number generator (with e.g. srandom(time(NULL))) sometime before you call it; otherwise the output won't be very random.

like image 137
Becca Royal-Gordon Avatar answered Oct 13 '22 10:10

Becca Royal-Gordon