I have a NSMutableArray of N Integer elements (N>4), I want to get 3 different random elements from this array. I do not really need a perfectly-uniform distribution, just 3 different random elements should be OK. Do you have any suggestion? Thanks
4 Answers
Make NSIndexSet
, and keep adding
int value = arc4random() % array.count;
items to it until its size gets to 3
. The you know that you have your three indexes.
NSMutableIndexSet *picks = [NSMutableIndexSet indexSet];
do {
[picks addIndex:arc4random() % array.count];
} while (picks.count != 3);
[picks enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSLog(@"Element at index %ud: %@", idx, [array elementAt:idx]);
}];

- 714,442
- 84
- 1,110
- 1,523
-
I do not really understand from the line `[picks enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { NSLog(@"Element at index %ud: %@", idx, [array elementAt:idx]); }]` . It just print out those 3 elements? – DavidNg Sep 09 '12 at 01:04
-
@DavidNg Yes, this is just an illustration of how you can use the `picks` set. The block in my example prints the there elements and their indexes, but of course you are free to use them in any way you want. – Sergey Kalinichenko Sep 09 '12 at 01:12
-
Thank you. Very nice! I added a Swift 4 version in a separate answer below. – Rodrigo Pinto Oct 18 '17 at 17:03
for (int i = 1; i <= 3; i++) {
int index = (int)(arc4random() % [array count]);
id object = [array objectAtIndex:index];
[array removeObjectAtIndex:index];
}
arc4random()
returns a random number in the range [0,2^32-1). The remainder when you take the modulus with the size of the array gets you a value between [0,arrayCountLessOne].
If you don't want to change your original data array, you can just make a copy of the array.

- 16,250
- 7
- 45
- 84
-
-
Instead of using `arc4random() % [array count]` you should use `arc4random_unform([array count])` to avoid modulo bias. See http://stackoverflow.com/a/29956021/796419 – smileyborg Dec 21 '16 at 19:39
If you want to do this more than once from various places in your code then consider doing this: The "Objective C way" is to create a category on NSMutableArray which adds a method randomObjects
. The method itself should generate three random integers from 0 to the length of the array -1 (N-1
), then return a set of objects from the array at those indices, as per the other answers here (dasblinkenlight's in particular.)
First, create the category. Create a new header file NSMutableArray+RandomObject.h
, containing:
@interface NSMutableArray (RandomObjects)
- (NSSet *) randomObjects;
@end
The RandomElement
in parentheses is the name of your category. Any class you write that includes this new header file will give all your NSMutableArray
instances the randomElement
method.
Then the implementation, in NSMutableArray+RandomObjects.m
:
@implementation NSMutableArray (RandomObjects)
- (NSSet *) randomObjects {
// Use the code from @dasblinkenlight's answer here, adding the following line:
return picks;
}
@end
And that's basically it. You've effectively added that capability to NSMutableArray
.

- 5,024
- 2
- 30
- 58
-
I would only refactor it into a category when I need to call such a method often enough. If its only used once, a category is way too much overkill for this. – JustSid Sep 09 '12 at 01:00
-
Nice answer from dasblinkenlight!
In Swift 4:
let indexes = NSMutableIndexSet()
if array.count > setSize {
repeat {
indexes.add(Int(arc4random_uniform(UInt32(array.count))))
} while (indexes.count < setSize)
}

- 2,384
- 22
- 23