Picking a Random Object in an NSArray

Objective CCocoa

Objective C Problem Overview


Say I have an array with objects, 1, 2, 3 and 4. How would I pick a random object from this array?

Objective C Solutions


Solution 1 - Objective C

@Darryl's answer is correct, but could use some minor tweaks:

NSUInteger randomIndex = arc4random() % theArray.count;

Modifications:

  • Using arc4random() over rand() and random() is simpler because it does not require seeding (calling srand() or srandom()).
  • The modulo operator (%) makes the overall statement shorter, while also making it semantically clearer.

Solution 2 - Objective C

This is the simplest solution I could come up with:

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

It's necessary to check count because a non-nil but empty NSArray will return 0 for count, and arc4random_uniform(0) returns 0. So without the check, you'll go out of bounds on the array.

This solution is tempting but is wrong because it will cause a crash with an empty array:

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

For reference, here's the [documentation][1]:

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 doesn't mention that arc4random_uniform returns 0 when 0 is passed as upper_bound.

Also, arc4random_uniform is defined in <stdlib.h>, but adding the #import wasn't necessary in my iOS test program.

[1]: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/arc4random_uniform.3.html "Official Apple Man Page for arc4random"

Solution 3 - Objective C

Perhaps something along the lines of:

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

Don't forget to initialize the random number generator (srandomdev(), for example).

NOTE: I've updated to use -count instead of dot syntax, per the answer below.

Solution 4 - Objective C

@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

Solution 5 - Objective C

Generate a random number and use it as the 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;
}

Solution 6 - Objective C

 srand([[NSDate date]  timeIntervalSince1970]);

 int inx =rand()%[array count];

inx is the random number.

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

Solution 7 - Objective C

ObjectType *objectVarName = [array objectAtIndex:arc4random_uniform((int)(array.count - 1))];

if you want to cast that to an int, here's the solution for that (useful for when you need a random int from an array of non-sequential numbers, in the case of randomizing an enum call, etc)

int intVarName = (int)[(NSNumber *)[array objectAtIndex:arc4random_uniform((int)(array.count - 1))] integerValue];

Solution 8 - Objective C

In Swift 4:

let array = ["one","two","three","four"]
let randomNumber = arc4random_uniform(UInt32(array.count))

array[Int(randomNumber)]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoshuaView Question on Stackoverflow
Solution 1 - Objective CDave DeLongView Answer on Stackoverflow
Solution 2 - Objective CfunrollView Answer on Stackoverflow
Solution 3 - Objective CDarryl H. ThomasView Answer on Stackoverflow
Solution 4 - Objective CAliaksandr BialiauskiView Answer on Stackoverflow
Solution 5 - Objective Cuser23743View Answer on Stackoverflow
Solution 6 - Objective CPathetic LearnerView Answer on Stackoverflow
Solution 7 - Objective CjungledevView Answer on Stackoverflow
Solution 8 - Objective CgargView Answer on Stackoverflow