Скажем, у меня есть массив с объектами, 1, 2, 3 и 4. Как бы я выбрал случайный объект из этого массива?
Выбор случайного объекта в NSArray
Ответ 1
@Даррил ответил правильно, но может использовать некоторые незначительные настройки:
NSUInteger randomIndex = arc4random() % [theArray count];
Модификации:
- Использование
arc4random()
надrand()
иrandom()
проще, потому что не требует посева (вызовsrand()
илиsrandom()
). - Оператор modulo (
%
) делает общий оператор короче, а также делает его семантически понятным. -
theArray.count
неверно. Он будет работать, ноcount
не объявляется как@property
наNSArray
, и поэтому не вызывается через точечный синтаксис. То, что он работает, просто является побочным эффектом интерпретации синтаксиса точки компилятором.
Ответ 2
Это самое простое решение, которое я мог бы придумать:
id object = array.count == 0 ? nil : array[arc4random_uniform(array.count)];
Необходимо проверить count
, потому что не nil
, но пустой NSArray
вернет 0
для count
, а arc4random_uniform(0)
возвращает 0
. Поэтому без проверки вы выйдете за пределы массива.
Это решение заманчиво, но неверно, потому что это приведет к сбою с пустым массивом:
id object = array[arc4random_uniform(array.count)];
Для справки: documentation:
u_int32_t
arc4random_uniform(u_int32_t upper_bound);
arc4random_uniform() will return a uniformly distributed random number less than upper_bound.
В man-странице не упоминается, что arc4random_uniform
возвращает 0
, когда 0
передается как upper_bound
.
Кроме того, arc4random_uniform
определяется в <stdlib.h>
, но добавление #import
не было необходимо в моей тестовой программе iOS.
Ответ 3
Возможно, что-то похожее:
NSUInteger randomIndex = (NSUInteger)floor(random()/RAND_MAX * [theArray count]);
Не забудьте инициализировать генератор случайных чисел (например, srandomdev()).
ПРИМЕЧАНИЕ. Я обновил для использования -count вместо синтаксиса точки в соответствии с нижеприведенным ответом.
Ответ 4
@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
Изменить: Обновлено для Xcode 7. Дженерики, nullability
Ответ 5
Создайте случайное число и используйте его как индекс. Пример:
#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;
}
Ответ 6
srand([[NSDate date] timeIntervalSince1970]);
int inx =rand()%[array count];
inx - случайное число.
где srand() может быть где угодно в программе перед функцией случайного выбора.
Ответ 7
ObjectType *objectVarName = [array objectAtIndex:arc4random_uniform((int)(array.count - 1))];
если вы хотите передать это в int, вот решение для этого (полезно, когда вам нужен случайный int из массива несекретных чисел, в случае рандомизации вызова enum и т.д.)
int intVarName = (int)[(NSNumber *)[array objectAtIndex:arc4random_uniform((int)(array.count - 1))] integerValue];
Ответ 8
В Swift 4:
let array = ["one","two","three","four"]
let randomNumber = arc4random_uniform(UInt32(array.count))
array[Int(randomNumber)]