Selecting a random object in NSArray

Let's say I have an array with objects, 1, 2, 3, and 4. How would I select a random object from this array?

+80
objective-c cocoa
Jul 23 2018-10-23T00:
source share
8 answers

@ Darryl answered correctly, but may use some minor tweaks:

NSUInteger randomIndex = arc4random() % [theArray count]; 

Modifications:

  • Using arc4random() over rand() and random() simpler because it does not require seeding (calling srand() or srandom() ).
  • The modulo operator ( % ) makes the general operator shorter, and also makes it semantically understandable.
  • theArray.count is incorrect. It will work, but count not declared as @property on NSArray , and therefore is not called via dot syntax. The fact that it works is simply a side effect of interpreting the point syntax by the compiler.
+183
Jul 23 '10 at 14:39
source share

This is the simplest solution I could come up with:

 id object = array.count == 0 ? nil : array[arc4random_uniform(array.count)]; 

You need to check count because it is not nil , but an empty NSArray will return 0 for count , and arc4random_uniform(0) return 0 . Therefore, without checking, you will go beyond the array.

This solution is tempting, but incorrect , because it will crash with an empty array:

 id object = array[arc4random_uniform(array.count)]; 

For reference: documentation :

 u_int32_t arc4random_uniform(u_int32_t upper_bound); arc4random_uniform() will return a uniformly distributed random number less than upper_bound. 

The man page does not mention that arc4random_uniform returns 0 when 0 is passed as upper_bound .

In addition, arc4random_uniform is defined in <stdlib.h> , but the addition of #import not necessary in my iOS test program.

+16
Nov 13 '13 at 15:11
source share

Maybe something similar:

 NSUInteger randomIndex = (NSUInteger)floor(random()/RAND_MAX * [theArray count]); 

Remember to initialize the random number generator (e.g. srandomdev ()).

NOTE. I updated to use -count instead of the point syntax as per the answer below.

+10
Jul 23 '10 at 14:19
source share
 @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 

Edit: Updated for Xcode 7. Generics, nullability

+9
Jul 09 '14 at 9:53 on
source share

Create a random number and use it as an index. Example:

 #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSArray *array = [NSArray arrayWithObjects: @"one", @"two", @"three", @"four", nil]; NSUInteger randomNumber; int fd = open("/dev/random", O_RDONLY); if (fd != -1) { read(fd, &randomNumber, sizeof(randomNumber)); close(fd); } else { fprintf(stderr, "Unable to open /dev/random: %s\n", strerror(errno)); return -1; } double scaledRandomNumber = ((double)randomNumber)/NSUIntegerMax * [array count]; NSUInteger randomIndex = (NSUInteger)floor(scaledRandomNumber); NSLog(@"random element: %@", [array objectAtIndex: randomIndex]); } return 0; } 
+1
Jul 23 '10 at 14:11
source share
  srand([[NSDate date] timeIntervalSince1970]); int inx =rand()%[array count]; 

inx is a random number.

where srand () can be anywhere in the program before the random function.

0
Dec 21 '11 at 6:59 a.m.
source share
 ObjectType *objectVarName = [array objectAtIndex:arc4random_uniform((int)(array.count - 1))]; 

if you want to pass this to int, here is the solution for this (useful when you need a random int from an array of unclassified numbers, in case of randomizing an enum call, etc.)

 int intVarName = (int)[(NSNumber *)[array objectAtIndex:arc4random_uniform((int)(array.count - 1))] integerValue]; 
0
Aug 7 '15 at 17:13
source share

In Swift 4:

 let array = ["one","two","three","four"] let randomNumber = arc4random_uniform(UInt32(array.count)) array[Int(randomNumber)] 
0
Oct 12 '17 at 19:34 on
source share



All Articles