modo canonico per randomizzare un NSArray nell’objective C

Esiste un modo canonico per randomizzare una matrice nell’objective C?

La mia libreria di utilità definisce questa categoria su NSMutableArray per farlo:

 @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 

Assicurati di aver seminato il generatore di numeri casuali (ad es. srandom(time(NULL)) ) prima che tu lo chiami; altrimenti l’output non sarà molto casuale.

Ecco qui!

 - (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)]; } 

Assicurati di avviare la funzione random () con srandomdev () o srandom ().

Non c’è nessuno integrato nell’SDK se è quello che stai chiedendo.

Puoi comunque utilizzare qualsiasi algoritmo di randomizzazione o shuffling che desideri. Diversi algoritmi hanno diversi compromessi in termini di casualità, efficienza, ecc.

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

Per gli algoritmi che mescolano “in-place”, inizia con un uso di array mutabile

 insertObject:atIndex: removeObjectAtIndex: 

Per gli algoritmi che ricostruiscono l’array, alimentarlo come originale e creare un nuovo array.

La mia soluzione è un metodo di categoria che restituisce una copia dell’array (autoreleased) con elementi randomizzati (usando 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 

Non c’è un modo canonico senza fare una categoria su NSArray (cioè avere un metodo di istanza come arrayWithRandomizedIndices ) o NSMutableArray (cioè avere un metodo come randomizeIndices ).

Ecco un esempio dalla mia libreria, parte di una categoria su NSMutableArray . Riorganizzerà casualmente l’array, piuttosto che rimescolare alcune voci.

 - (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]; } 

Chiama srand(time(0)); o alcuni di questi prima di chiamare questo metodo o all'inizio del metodo.

Randomizzazione NSArray come metodo di categoria 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 

Come visto: NSArray Randomization & Psychedelia