该答案详细说明了如何在Swift 4.2+中使用快速统一的算法(Fisher-
Yates)进行改组,以及如何在各个早期版本的Swift中添加相同功能。每个Swift版本的命名和行为都与该版本的变异和非变异排序方法匹配。
shuffle并且
shuffled是从Swift
4.2开始原生的 用法示例:
Swift 4.0和4.1let x = [1, 2, 3].shuffled()// x == [2, 3, 1]let fiveStrings = stride(from: 0, through: 100, by: 5).map(String.init).shuffled()// fiveStrings == ["20", "45", "70", "30", ...]var numbers = [1, 2, 3, 4]numbers.shuffle()// numbers == [3, 2, 1, 4]
这些扩展将
shuffle()方法添加到任何可变集合(数组和不安全的可变缓冲区),并
shuffled()在任何序列上添加方法:
extension MutableCollection { /// Shuffles the contents of this collection. mutating func shuffle() { let c = count guard c > 1 else { return } for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) { // Change `Int` in the next line to `IndexDistance` in < Swift 4.1 let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount))) let i = index(firstUnshuffled, offsetBy: d) swapAt(firstUnshuffled, i) } }}extension Sequence { /// Returns an array with the contents of this sequence, shuffled. func shuffled() -> [Element] { var result = Array(self) result.shuffle() return result }}
与上述Swift 4.2示例中的用法相同。
迅捷3
这些扩展将
shuffle()方法添加到任何可变集合中,并将
shuffled()方法添加到任何序列中:
extension MutableCollection where Indices.Iterator.Element == Index { /// Shuffles the contents of this collection. mutating func shuffle() { let c = count guard c > 1 else { return } for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) { // Change `Int` in the next line to `IndexDistance` in < Swift 3.2 let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount))) guard d != 0 else { continue } let i = index(firstUnshuffled, offsetBy: d) self.swapAt(firstUnshuffled, i) } }}extension Sequence { /// Returns an array with the contents of this sequence, shuffled. func shuffled() -> [Iterator.Element] { var result = Array(self) result.shuffle() return result }}
与上述Swift 4.2示例中的用法相同。
迅捷2
(过时的语言:自2018年7月起,您将无法使用Swift 2.x在iTunes Connect上发布)
extension MutableCollectionType where Index == Int { /// Shuffle the elements of `self` in-place. mutating func shuffleInPlace() { // empty and single-element collections don't shuffle if count < 2 { return } for i in startIndex ..< endIndex - 1 { let j = Int(arc4random_uniform(UInt32(count - i))) + i guard i != j else { continue } swap(&self[i], &self[j]) } }}extension CollectionType { /// Return a copy of `self` with its elements shuffled. func shuffle() -> [Generator.Element] { var list = Array(self) list.shuffleInPlace() return list }}
用法:
[1, 2, 3].shuffle()// [2, 3, 1]let fiveStrings = 0.stride(through: 100, by: 5).map(String.init).shuffle()// ["20", "45", "70", "30", ...]var numbers = [1, 2, 3, 4]numbers.shuffleInPlace()// [3, 2, 1, 4]
斯威夫特1.2
(过时的语言:自2018年7月起,您将无法使用Swift 1.x在iTunes Connect上发布)
shuffle作为变异数组方法
通过此扩展,您可以
Array在适当位置随机播放可变实例:
extension Array { mutating func shuffle() { if count < 2 { return } for i in 0..<(count - 1) { let j = Int(arc4random_uniform(UInt32(count - i))) + i swap(&self[i], &self[j]) } }}var numbers = [1, 2, 3, 4, 5, 6, 7, 8]numbers.shuffle() // e.g., numbers == [6, 1, 8, 3, 2, 4, 7, 5]
shuffled作为非变异数组方法
通过此扩展,您可以检索
Array实例的随机组合副本:
extension Array { func shuffled() -> [T] { if count < 2 { return self } var list = self for i in 0..<(list.count - 1) { let j = Int(arc4random_uniform(UInt32(list.count - i))) + i swap(&list[i], &list[j]) } return list }}let numbers = [1, 2, 3, 4, 5, 6, 7, 8]let mixedup = numbers.shuffled() // e.g., mixedup == [6, 1, 8, 3, 2, 4, 7, 5]
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)