稍微改进和简洁的解决方案(与最佳答案相比)。
该算法是相同的并且在文献中被描述为“ 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])
}
}
}
注意:在 Swift 中更简洁的解决方案可以从 iOS10 使用GameplayKit
.
注意:不稳定洗牌的算法(如果计数> 1,所有位置都强制改变)也可用