如何随机化或混洗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得到所有这些更复制粘贴的格式。