I have a large NSArray of names, I need to get random 4 records (names) from that array, how can I do that?
Asked
Active
Viewed 4,726 times
3 Answers
21
#include <stdlib.h>
NSArray* names = ...;
NSMutableArray* pickedNames = [NSMutableArray new];
int remaining = 4;
if (names.count >= remaining) {
while (remaining > 0) {
id name = names[arc4random_uniform(names.count)];
if (![pickedNames containsObject:name]) {
[pickedNames addObject:name];
remaining--;
}
}
}

Andrey Zverev
- 4,409
- 1
- 28
- 34

Julio Gorgé
- 10,056
- 2
- 45
- 60
-
3True, I just replaced rand() by arc4random() which is superior and does not need seeding. – Julio Gorgé Apr 30 '11 at 06:03
-
Thank you, it works fine. But, I think that pickedNames should be NSMutableArray – Tunyk Pavel Apr 30 '11 at 06:05
-
Yes, should be NSMutableArray indeed. – Julio Gorgé Apr 30 '11 at 06:06
-
1This could be optimised for some situations by making names be a mutable array, and removing names once they are picked (and you could also then take out the containsObject check). Imagine if you have (for example) a situation where you are picking 10,000 items from an array with 10,001 members. In the current answer the while loop will do many thousands of unsuccessful iterations. With this optimisation it will do zero unsuccessful iterations. (Obviously in my extreme example a more efficient way could be to chose one item and remove it, but it is just for illustration) – narco Apr 17 '16 at 09:13
2
I made a caregory called NSArray+RandomSelection
. Just import this category into a project, and then just use
NSArray *things = ...
...
NSArray *randomThings = [things randomSelectionWithCount:4];
Here's the implementation:
NSArray+RandomSelection.h
@interface NSArray (RandomSelection)
- (NSArray *)randomSelectionWithCount:(NSUInteger)count;
@end
NSArray+RandomSelection.m
@implementation NSArray (RandomSelection)
- (NSArray *)randomSelectionWithCount:(NSUInteger)count {
if ([self count] < count) {
return nil;
} else if ([self count] == count) {
return self;
}
NSMutableSet* selection = [[NSMutableSet alloc] init];
while ([selection count] < count) {
id randomObject = [self objectAtIndex: arc4random() % [self count]];
[selection addObject:randomObject];
}
return [selection allObjects];
}
@end

mopsled
- 8,445
- 1
- 38
- 40
-
2The handling for random selection larger then the array is incorrect. I am using the following instead of the first 5 lines: `if ([self count] < count) { count = [self count]; }` – miho Oct 04 '12 at 09:01
-
if you have less than 'count' unique elements in the array, you'll end up in and endless loop – Pieter Sep 26 '13 at 12:33
2
If you prefer a Swift Framework that also has some more handy features feel free to checkout HandySwift. You can add it to your project via Carthage then use it like this:
import HandySwift
let names = ["Harry", "Hermione", "Ron", "Albus", "Severus"]
names.sample() // => "Hermione"
There is also an option to get multiple random elements at once:
names.sample(size: 3) // => ["Ron", "Albus", "Harry"]
I hope this helps!

Jeehut
- 20,202
- 8
- 59
- 80
-
This doesn't answer the question as you need to show how the list of random numbers can be used to select the names in the large array in order to creat the picked names array. – Droppy Jun 09 '16 at 21:13
-
1It seems my answer was misleading. I've updated it to use a names array as an example instead of a numbers array. Works the same, just a different type of Array. I hope it's clear now. – Jeehut Jun 09 '16 at 21:21