Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one retrieve a random object from an NSSet instance?

I can grab a random value from an array-like structure by retrieving a random index.

How can I grab a random value from an NSSet object that stores NSNumber objects? I couldn't find an instance method of NSSet that retrieves a random value.

like image 957
Billy Goswell Avatar asked Apr 02 '12 18:04

Billy Goswell


2 Answers

In short, you can't directly retrieve a random object from an NSSet.

You either need to turn the set into an array -- into something that has an index that can be randomized -- by re-architecting your code to use an array or you could implement this using this bit of pseudo-code:

randomIndex = ...random-generator....(0 .. [set count]);
__block currentIndex = 0;
__block selectedObj = nil;
[set enumerateObjectsWithOptions:^(id obj, BOOL *stop) {
    if (randomIndex == currentIndex) { selectedObj = obj; *stop = YES }
    else currentIndex++;
 }];
 return selectedObj;

Yes -- it iterates the set, potentially the whole set, when grabbing the object. However, that iteration is pretty much what'll happen in the conversion to an NSArray anyway. As long as the set isn't that big and you aren't calling it that often, no big deal.

like image 108
bbum Avatar answered Nov 15 '22 02:11

bbum


Whilst I like that @bbum answer will terminate early on some occasions due to the use of stop in the enumeration block.

For readability and ease of remembering what is going on when you revisit this code in the future I would go with his first suggestion of turn the set into an array

NSInteger randomIndex = ..random-generator....(0 .. [set count])
id obj = [set count] > 0 ? [[set allObjects] objectAtIndex:randomIndex] : nil;
like image 41
Paul.s Avatar answered Nov 15 '22 03:11

Paul.s