1 个回答

Brent Royal-Gordon
我的工具库在NSMutableArray定义了这个类,以实现随机化数组:

@interface NSMutableArray (ArchUtils_Shuffle)
- (void)shuffle;
@end

// 选择一个n以下的随机整数 
// 计算m, 2的幂略高于n, 然后采用 random() 模数m,
// 如果在n和m之间就扔掉随机数
// (更多单纯的方法, 比如采用random()模数n, 介绍一个偏置)
// 倾向范围内较小的数字
static NSUInteger random_below(NSUInteger n) {
    NSUInteger m = 1;

    //计算比n更大的两个最小的幂 
// 或许有比这个循环更加快速的解决办法,除了位变换
// 不是我的专长.
    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))),否则输出的就不是随机数。
Abramodj
解决办法在这:

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

Nathan Kinsinger

if ([array count] > 1) {
    for (NSUInteger shuffleIndex = [array count] - 1; shuffleIndex > 0; shuffleIndex--)
        [array exchangeObjectAtIndex:shuffleIndex withObjectAtIndex:random() % (shuffleIndex + 1)];
}

确保使用srandomdev() 或 srandom()构造random()功能


amattn
没有你要求的那种内置的SDK
你可以使用任何你想要的随机或洗牌算法。不同的算法在随机性、效率等方面有不同的权衡。
http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms
对于使用可变数组开始的适当洗牌的算法使用:

insertObject:atIndex:
removeObjectAtIndex:

对于重建阵列算法, 提供原来的并建立一个新的阵列。


SK9
在NSArray(也就是说有个类似arrayWithRandomizedIndices的实例方法)或者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)); ,或者调用这个方法之前的类似的,或是该方法的早期。


Chris Miles
我的解决办法是用一个类的方法,使用随机元素(使用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 

Cirrostratus
作为Objective-C 类方法的NSArray随机化:

@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

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进