How do I shuffle an array in Swift? -
how randomize or shuffle elements within array in swift? example, if array consists of 52 playing cards, want shuffle array in order shuffle deck.
this answer details how add fisher-yates (fast uniform) shuffle in various versions of swift. swift 3 & 4 versions permissive, @ least work arrays. naming , behavior each swift version matches mutating , nonmutating sorting methods version.
swift 4
these extensions add shuffle()
method mutable collection (arrays , unsafe mutable buffers) , shuffled()
method sequence:
extension mutablecollection { /// shuffles contents of collection. mutating func shuffle() { let c = count guard c > 1 else { return } (firstunshuffled, unshuffledcount) in zip(indices, stride(from: c, to: 1, by: -1)) { let d: indexdistance = numericcast(arc4random_uniform(numericcast(unshuffledcount))) let = index(firstunshuffled, offsetby: d) swapat(firstunshuffled, i) } } } extension sequence { /// returns array contents of sequence, shuffled. func shuffled() -> [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, 2, 3, 4] numbers.shuffle() // numbers == [3, 2, 1, 4]
swift 3
these extensions add shuffle()
method mutable collection , shuffled()
method sequence:
extension mutablecollection indices.iterator.element == index { /// shuffles contents of collection. mutating func shuffle() { let c = count guard c > 1 else { return } (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 = index(firstunshuffled, offsetby: d) swap(&self[firstunshuffled], &self[i]) } } } extension sequence { /// returns array contents of 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, 2, 3, 4] numbers.shuffle() // numbers == [3, 2, 1, 4]
swift 2
extension mutablecollectiontype index == int { /// shuffle elements of `self` in-place. mutating func shuffleinplace() { // empty , single-element collections don't shuffle if count < 2 { return } in startindex ..< endindex - 1 { let j = int(arc4random_uniform(uint32(count - i))) + guard != j else { continue } swap(&self[i], &self[j]) } } } extension collectiontype { /// return copy of `self` 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]
swift 1.2
shuffle
function
this simplest version: add function anywhere @ top level , you'll able shuffle arrays , slices:
func shuffle<c: mutablecollectiontype c.index == int>(var list: c) -> c { let c = count(list) if c < 2 { return list } in 0..<(c - 1) { let j = int(arc4random_uniform(uint32(c - i))) + swap(&list[i], &list[j]) } return list } shuffle([1, 2, 3, 4, 5, 6, 7, 8]) // e.g., [6, 1, 8, 3, 2, 4, 7, 5] shuffle(["hello", "goodbye", "ciao"]) // e.g., ["ciao", "goodbye", "hello"]
shuffle
mutating array method
this extension let shuffle mutable array
instance in place:
extension array { mutating func shuffle() { if count < 2 { return } in 0..<(count - 1) { let j = int(arc4random_uniform(uint32(count - 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
non-mutating array method
this extension let retrieve shuffled copy of array
instance:
extension array { func shuffled() -> [t] { if count < 2 { return self } var list = self in 0..<(list.count - 1) { let j = int(arc4random_uniform(uint32(list.count - 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]
Comments
Post a Comment