Billy Goswell
Billy Goswell

Reputation: 205

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.

Upvotes: 7

Views: 2458

Answers (2)

Paul.s
Paul.s

Reputation: 38728

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;

Upvotes: 4

bbum
bbum

Reputation: 162722

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.

Upvotes: 5

Related Questions