Disons que j'ai un tableau avec des objets, 1, 2, 3 et 4. Comment choisirais-je un objet aléatoire dans ce tableau?
Disons que j'ai un tableau avec des objets, 1, 2, 3 et 4. Comment choisirais-je un objet aléatoire dans ce tableau?
Réponses:
La réponse de @ Darryl est correcte, mais pourrait nécessiter quelques ajustements mineurs:
NSUInteger randomIndex = arc4random() % theArray.count;
Modifications:
arc4random()
over rand()
and random()
est plus simple car elle ne nécessite pas d'amorçage (appel srand()
ou srandom()
).%
) rend l'instruction globale plus courte, tout en la rendant sémantiquement plus claire.0 % 4 = 0
, 1 % 4 = 1
, 2 % 4 = 2
, 3 % 4 = 3
, 4 % 4 = 0
, 5 % 4 = 1
... Si vous modulo par n , votre plus grand résultat ne sera jamais supérieure à n-1 .
count
est une propriété:@interface NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> @property (readonly) NSUInteger count;
C'est la solution la plus simple que je pourrais trouver:
id object = array.count == 0 ? nil : array[arc4random_uniform(array.count)];
Il est nécessaire de vérifier count
car un non- nil
mais vide NSArray
retournera 0
pour count
et arc4random_uniform(0)
retourne 0
. Donc, sans le chèque, vous sortirez des limites du tableau.
Cette solution est tentante mais est erronée car elle provoquera un crash avec un tableau vide:
id object = array[arc4random_uniform(array.count)];
Pour référence, voici 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 page de manuel ne mentionne pas que arc4random_uniform
renvoie 0
quand 0
est passé comme upper_bound
.
Aussi, arc4random_uniform
est défini dans <stdlib.h>
, mais l'ajout #import
n'était pas nécessaire dans mon programme de test iOS.
Peut-être quelque chose du genre:
NSUInteger randomIndex = (NSUInteger)floor(random()/RAND_MAX * [theArray count]);
N'oubliez pas d'initialiser le générateur de nombres aléatoires (srandomdev (), par exemple).
REMARQUE: j'ai mis à jour pour utiliser -count au lieu de la syntaxe dot, conformément à la réponse ci-dessous.
@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
Edit: mis à jour pour Xcode 7. Generics, nullability
Générez un nombre aléatoire et utilisez-le comme index. Exemple:
#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()
pour obtenir des nombres aléatoires cryptographiquement utiles, sur l'iPhone de toute façon. Sur Mac, vous avez un accès direct à / dev / random.
srand([[NSDate date] timeIntervalSince1970]);
int inx =rand()%[array count];
inx est le nombre aléatoire.
où srand () peut être n'importe où dans le programme avant la fonction de sélection aléatoire.
ObjectType *objectVarName = [array objectAtIndex:arc4random_uniform((int)(array.count - 1))];
si vous voulez convertir cela en un int, voici la solution pour cela (utile lorsque vous avez besoin d'un int aléatoire à partir d'un tableau de nombres non séquentiels, dans le cas de la randomisation d'un appel enum, etc.)
int intVarName = (int)[(NSNumber *)[array objectAtIndex:arc4random_uniform((int)(array.count - 1))] integerValue];
Dans Swift 4:
let array = ["one","two","three","four"]
let randomNumber = arc4random_uniform(UInt32(array.count))
array[Int(randomNumber)]
arc4random_uniform
méthode pour éviter les biais modulo.