如何随机化或混洗Swift中的数组中的元素?例如,如果我的数组包括52张扑克牌,我想洗牌,以便洗牌。
这个答案详细说明了如何在Swift的各种版本中添加Fisher-Yates(快速统一)shuffle。 Swift 3版本是最宽松的,但是它们至少可以用于数组。每个Swift版本的命名和行为与该版本的mutating和nonmutating排序方法相匹配。
Swift 3.0
这些扩展添加一个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)) { let d: Indexdistance = numericCast(arc4random_uniform(numericCast(unshuffledCount))) guard d != 0 else { continue } let i = index(firstUnshuffled,offsetBy: d) swap(&self[firstUnshuffled],&self[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 } } let 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,4] numbers.shuffle() // numbers == [3,1,4]
Swift 2.0
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,3].shuffle() // [2,1] let fiveStrings = 0.stride(through: 100,by: 5).map(String.init).shuffle() // ["20",4] numbers.shuffleInPlace() // [3,4]
Swift 1.2
shuffle作为函数
这是最简单的版本:在顶层任何地方添加此函数,您可以随机播放数组和切片:
func shuffle<C: MutableCollectionType where C.Index == Int>(var list: C) -> C { let c = count(list) if c < 2 { return list } for i in 0..<(c - 1) { let j = Int(arc4random_uniform(UInt32(c - i))) + i swap(&list[i],&list[j]) } return list } shuffle([1,4,5,6,7,8]) // e.g.,[6,8,5] shuffle(["hello","goodbye","Ciao"]) // e.g.,["Ciao","hello"]
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,8] numbers.shuffle() // e.g.,numbers == [6,5]
改组为非突变数组方法
此扩展将允许您检索数组实例的随机副本:
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,8] let mixedup = numbers.shuffled() // e.g.,mixedup == [6,5]
你可以从this gist得到所有这些更复制粘贴的格式。