略有改进和简洁的解决方案(与最佳答案相比)。
该算法是相同的,在文献中被描述为“ Fisher-Yates shuffle ”。
在Objective-C中:
@implementation NSMutableArray (Shuffle)
// Fisher-Yates shuffle
- (void)shuffle
{
for (NSUInteger i = self.count; i > 1; i--)
[self exchangeObjectAtIndex:i - 1 withObjectAtIndex:arc4random_uniform((u_int32_t)i)];
}
@end
在Swift 3.2和4.x中:
extension Array {
/// Fisher-Yates shuffle
mutating func shuffle() {
for i in stride(from: count - 1, to: 0, by: -1) {
swapAt(i, Int(arc4random_uniform(UInt32(i + 1))))
}
}
}
在Swift 3.0和3.1中:
extension Array {
/// Fisher-Yates shuffle
mutating func shuffle() {
for i in stride(from: count - 1, to: 0, by: -1) {
let j = Int(arc4random_uniform(UInt32(i + 1)))
(self[i], self[j]) = (self[j], self[i])
}
}
}
注意:从iOS10使用,可以在Swift中提供更简洁的解决方案GameplayKit
。
注意:还提供了一种用于不稳定混洗的算法(如果count> 1,则所有位置都必须更改)