канонический способ рандомизации NSArray в Objective C

Существует ли канонический способ рандомизации массива в Objective C?

Моя библиотека утилиты определяет эту категорию в NSMutableArray для этого:

 @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 

Убедитесь, что вы srandom(time(NULL)) генератор случайных чисел (например, srandom(time(NULL)) ), прежде чем вы его srandom(time(NULL)) ; иначе выход не будет очень случайным.

Вот!

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

Убедитесь, что вы выбрали функцию random () либо srandomdev (), либо srandom ().

В SDK нет встроенного SDK, если это то, о чем вы просите.

Вы можете использовать практически любой алгоритм рандомизации или перетасовки, который вы хотите. Различные алгоритмы имеют разные компромиссы с точки зрения случайности, эффективности и т. Д.

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

Для алгоритмов, которые перетасовывают «на месте», начинаются с использования изменяемого массива

 insertObject:atIndex: removeObjectAtIndex: 

Для алгоритмов, которые восстанавливают массив, загрузите его оригиналом и создайте новый массив.

Мое решение – это метод категории, который возвращает копию массива (autoreleased) с рандомизированными элементами (используя 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 

Существует не канонический способ, не создавая категорию на NSArray (т. arrayWithRandomizedIndices метод экземпляра, такой как arrayWithRandomizedIndices ) или NSMutableArray (т. NSMutableArray такой метод, как randomizeIndices ).

Вот пример из моей библиотеки, часть категории в NSMutableArray . Он будет произвольно переупорядочивать массив, а не перетасовывать несколько записей.

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

Вызов srand(time(0)); или некоторые из них до вызова этого метода или в начале метода.

Рандомизация NSArray как метод classа 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 в @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 

Как видно: NSArray Randomization & Psychedelia

  • Производить случайные числа равномерно по всему диапазону
  • Почему class System.Random не статичен?
  • Произвольное генерирование букв в соответствии с их частотой использования?
  • Как работают модуль и rand ()?
  • Почему я получаю одну и ту же последовательность для каждого запуска с помощью std :: random_device с mingw gcc4.8.1?
  • Как лучше всего моделировать произвольную одномерную случайную переменную с использованием ее вероятностной функции?
  • Могу ли я генерировать случайное число внутри пиксельного шейдера?
  • Как работает генератор случайных чисел?
  • Сколько случайных элементов перед MD5 вызывает столкновения?
  • Как создать список номеров без дубликатов?
  • Java: случайное длинное число в диапазоне 0 <= x <n
  • Interesting Posts
    Давайте будем гением компьютера.