verificar revista lecturas horas home gubernamental etica ethos certificacion cdpe acceso objective-c cocoa

objective-c - lecturas - revista ethos



Escogiendo un objeto aleatorio en un NSArray (8)

En Swift 4:

let array = ["one","two","three","four"] let randomNumber = arc4random_uniform(UInt32(array.count)) array[Int(randomNumber)]

Supongamos que tengo una matriz con objetos, 1, 2, 3 y 4. ¿Cómo podría elegir un objeto aleatorio de esta matriz?


Esta es la solución más simple que podría encontrar:

id object = array.count == 0 ? nil : array[arc4random_uniform(array.count)];

Es necesario verificar el count porque un NSArray no nil pero vacío devolverá 0 para count , y arc4random_uniform(0) devolverá 0 . Entonces sin el cheque, saldrás de límites en la matriz.

Esta solución es tentadora, pero está mal porque causará un bloqueo con una matriz vacía:

id object = array[arc4random_uniform(array.count)];

Como referencia, aquí está la documentation :

u_int32_t arc4random_uniform(u_int32_t upper_bound); arc4random_uniform() will return a uniformly distributed random number less than upper_bound.

La página man no menciona que arc4random_uniform devuelve 0 cuando 0 se pasa como upper_bound .

Además, arc4random_uniform se define en <stdlib.h> , pero no fue necesario agregar #import en mi programa de prueba de iOS.


Genere un número aleatorio y úselo como índice. Ejemplo:

#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; }


La respuesta de @Darryl es correcta, pero podría usar algunos ajustes menores:

NSUInteger randomIndex = arc4random() % [theArray count];

Modificaciones:

  • Usar arc4random() sobre rand() y random() es más simple porque no requiere siembra (llamando a srand() o srandom() ).
  • El operador de módulo ( % ) hace que la instrucción global sea más corta, a la vez que la vuelve semánticamente más clara.
  • theArray.count está mal. Funcionará, pero el count no se declara como @property en NSArray y, por lo tanto, no se debe invocar mediante la sintaxis de punto. Que funcione es simplemente un efecto secundario de cómo el compilador interpreta la sintaxis de punto.

Tal vez algo como:

NSUInteger randomIndex = (NSUInteger)floor(random()/RAND_MAX * [theArray count]);

No olvide inicializar el generador de números aleatorios (srandomdev (), por ejemplo).

NOTA: He actualizado para usar -count en lugar de sintaxis de punto, según la respuesta a continuación.


srand([[NSDate date] timeIntervalSince1970]); int inx =rand()%[array count];

inx es el número aleatorio.

donde srand () puede estar en cualquier parte del programa antes de la función de selección aleatoria.


@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

Editar: actualizado para Xcode 7. Generics, Nullability


ObjectType *objectVarName = [array objectAtIndex:arc4random_uniform((int)(array.count - 1))];

si quieres convertirlo en un int, aquí está la solución para eso (útil para cuando necesitas un int aleatorio de una matriz de números no secuenciales, en el caso de aleatorizar una llamada enum, etc.)

int intVarName = (int)[(NSNumber *)[array objectAtIndex:arc4random_uniform((int)(array.count - 1))] integerValue];