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