manière canonique de randomiser un NSArray dans l’Objectif C

Existe-t-il une manière canonique de randomiser un tableau dans l’objective C?

Ma bibliothèque d’utilitaires définit cette catégorie sur NSMutableArray pour le faire:

 @interface NSMutableArray (ArchUtils_Shuffle) - (void)shuffle; @end // Chooses a random integer below n without bias. // Computes m, a power of two slightly above n, and takes random() modulo m, // then throws away the random number if it's between n and m. // (More naive techniques, like taking random() modulo n, introduce a bias // towards smaller numbers in the range.) static NSUInteger random_below(NSUInteger n) { NSUInteger m = 1; // Compute smallest power of two greater than n. // There's probably a faster solution than this loop, but bit-twiddling // isn't my specialty. do { m <<= 1; } while(m < n); NSUInteger ret; do { ret = random() % m; } while(ret >= n); return ret; } @implementation NSMutableArray (ArchUtils_Shuffle) - (void)shuffle { // http://en.wikipedia.org/wiki/Knuth_shuffle for(NSUInteger i = [self count]; i > 1; i--) { NSUInteger j = random_below(i); [self exchangeObjectAtIndex:i-1 withObjectAtIndex:j]; } } @end 

Assurez-vous de placer le générateur de nombres aléatoires (avec par exemple srandom(time(NULL)) ) avant de l’appeler; sinon la sortie ne sera pas très aléatoire.

C’est ici!

 - (NSArray*)shuffleArray:(NSArray*)array { NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:array]; for(NSUInteger i = [array count]; i > 1; i--) { NSUInteger j = arc4random_uniform(i); [temp exchangeObjectAtIndex:i-1 withObjectAtIndex:j]; } return [NSArray arrayWithArray:temp]; } 
 if ([array count] > 1) { for (NSUInteger shuffleIndex = [array count] - 1; shuffleIndex > 0; shuffleIndex--) [array exchangeObjectAtIndex:shuffleIndex withObjectAtIndex:random() % (shuffleIndex + 1)]; } 

Assurez-vous de placer la fonction random () avec srandomdev () ou srandom ().

Il n’y en a pas dans le SDK si c’est ce que vous demandez.

Vous pouvez cependant utiliser n’importe quel algorithme de randomisation ou de mélange. Différents algorithmes ont des compromis différents en termes de caractère aléatoire, d’efficacité, etc.

http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms

Pour les algorithmes qui mélangent “in-place”, commencez par utiliser un tableau mutable

 insertObject:atIndex: removeObjectAtIndex: 

Pour les algorithmes qui reconstruisent le tableau, alimentez-le en original et créez un nouveau tableau.

Ma solution est une méthode de catégorie qui renvoie une copie du tableau (autoreleased) avec des éléments randomisés (en utilisant arc4random).

 @interface NSArray (CMRandomised) /* Returns a copy of the array with elements re-ordered randomly */ - (NSArray *)randomised; @end /* Returns a random integer number between low and high inclusive */ static inline int randomInt(int low, int high) { return (arc4random() % (high-low+1)) + low; } @implementation NSArray (CMRandomised) - (NSArray *)randomised { NSMutableArray *randomised = [NSMutableArray arrayWithCapacity:[self count]]; for (id object in self) { NSUInteger index = randomInt(0, [randomised count]); [randomised insertObject:object atIndex:index]; } return randomised; } @end 

Il n’y a pas de méthode canonique sans faire une catégorie sur NSArray (c’est-à-dire avoir une méthode d’instance comme arrayWithRandomizedIndices ) ou NSMutableArray (c’est-à-dire avoir une méthode comme randomizeIndices ).

Voici un exemple de ma bibliothèque, qui fait partie d’une catégorie sur NSMutableArray . Il réordonnera aléatoirement le tableau plutôt que de mélanger quelques entrées.

 - (void) randomizeIndices { if (self == nil || [self count] <= 1) { return; } int count = [self count]; NSMutableArray* copySelf = [NSMutableArray arrayWithArray:self]; NSMutableArray* mutableResultArray = [NSMutableArray alloc]; mutableResultArray = [mutableResultArray initWithCapacity:count]; [mutableResultArray autorelease]; int objectsMovedCount = 0; for (int i = 0; i < count; i++) { int index = rand() % (count - objectsMovedCount); id anObject = [copySelf objectAtIndex:index]; [mutableResultArray addObject:anObject]; [copySelf removeObjectAtIndex:index]; objectsMovedCount++; } [self setArray:mutableResultArray]; } 

Appel srand(time(0)); ou certains tels avant d'appeler cette méthode ou au début de la méthode.

La randomisation NSArray comme méthode de catégorie Objective-C:

 @implementation NSArray (NGDataDynamics) - (NSArray *)jumbled { NSMutableArray *jumbled = self.mutableCopy; NSUInteger idx = self.count-1; while(idx) { [jumbled exchangeObjectAtIndex:idx withObjectAtIndex:arc4random_uniform(idx)]; idx--; } return jumbled; } @end 

Comme vu: Randomisation NSArray & Psychedelia