.shuffle() and .shuffled() are part of Swift
Original historic question:
How do I randomize or shuffle the elements within an array in Swift? For example, if my array consists of 52 playing cards, I want to shuffle the array in order to shuffle the deck.
This answer details how to shuffle with a fast and uniform algorithm (Fisher-Yates) in Swift 4.2+ and how to add the same feature in the various previous versions of Swift. The naming and behavior for each Swift version matches the mutating and nonmutating sorting methods for that version.
Swift 4.2+
shuffle and shuffled are native starting Swift 4.2. Example usage:
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 4.0 and 4.1
These extensions add a shuffle() method to any mutable collection (arrays and unsafe mutable buffers) and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 3
These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 2
(obsolete language: you can't use Swift 2.x to publish on iTunes Connect starting July 2018)
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
}
}
Usage:
[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
(obsolete language: you can't use Swift 1.x to publish on iTunes Connect starting July 2018)
shuffle as a mutating array method
This extension will let you shuffle a mutable Array instance in place:
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 as a non-mutating array method
This extension will let you retrieve a shuffled copy of an Array instance:
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]
Edit: As noted in other answers, Swift 4.2 finally adds random number generation to the standard library, complete with array shuffling.
However, the GKRandom / GKRandomDistribution suite in GameplayKit can still be useful with the new RandomNumberGenerator protocol — if you add extensions to the GameplayKit RNGs to conform to the new standard library protocol, you can easily get:
sendable RNGs (that can reproduce a "random" sequence when needed for testing)
RNGs that sacrifice robustness for speed
RNGs that produce non-uniform distributions
...and still make use of the nice new "native" random APIs in Swift.
The rest of this answer concerns such RNGs and/or their use in older Swift compilers.
There are some good answers here already, as well as some good illustrations of why writing your own shuffle can be error-prone if you're not careful.
In iOS 9, macOS 10.11, and tvOS 9 (or later), you don't have to write your own. There's an efficient, correct implementation of Fisher-Yates in GameplayKit (which, despite the name, is not just for games).
If you just want a unique shuffle:
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
If you want to be able to replicate a shuffle or series of shuffles, choose and seed a specific random source; e.g.
let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)
In iOS 10 / macOS 10.12 / tvOS 10, there's also a convenience syntax for shuffling via an extension on NSArray. Of course, that's a little cumbersome when you're using a Swift Array (and it loses its element type on coming back to Swift):
let shuffled1 = (array as NSArray).shuffled(using: random) // -> [Any]
let shuffled2 = (array as NSArray).shuffled() // use default random source
But it's pretty easy to make a type-preserving Swift wrapper for it:
extension Array {
func shuffled(using source: GKRandomSource) -> [Element] {
return (self as NSArray).shuffled(using: source) as! [Element]
}
func shuffled() -> [Element] {
return (self as NSArray).shuffled() as! [Element]
}
}
let shuffled3 = array.shuffled(using: random)
let shuffled4 = array.shuffled()
In Swift 2.0, GameplayKit may come to the rescue! (supported by iOS9 or later)
import GameplayKit
func shuffle() {
array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}
Here's something possibly a little shorter:
sorted(a) {_, _ in arc4random() % 2 == 0}
Taking Nate's algorithm I wanted to see how this would look with Swift 2 and protocol extensions.
This is what I came up with.
extension MutableCollectionType where Self.Index == Int {
mutating func shuffleInPlace() {
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&self[i], &self[j])
}
}
}
extension MutableCollectionType where Self.Index == Int {
func shuffle() -> Self {
var r = self
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&r[i], &r[j])
}
return r
}
}
Now, any MutableCollectionType can use these methods given it uses Int as an Index
As of swift 4.2 there are two handy functions:
// shuffles the array in place
myArray.shuffle()
and
// generates a new array with shuffled elements of the old array
let newArray = myArray.shuffled()
In my case, I had some problems of swapping objects in Array. Then I scratched my head and went for reinventing the wheel.
// swift 3.0 ready
extension Array {
func shuffled() -> [Element] {
var results = [Element]()
var indexes = (0 ..< count).map { $0 }
while indexes.count > 0 {
let indexOfIndexes = Int(arc4random_uniform(UInt32(indexes.count)))
let index = indexes[indexOfIndexes]
results.append(self[index])
indexes.remove(at: indexOfIndexes)
}
return results
}
}
This is a version of Nate's implementation of the Fisher-Yates shuffle for Swift 4
(Xcode 9).
extension MutableCollection {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
for i in indices.dropLast() {
let diff = distance(from: i, to: endIndex)
let j = index(i, offsetBy: numericCast(arc4random_uniform(numericCast(diff))))
swapAt(i, j)
}
}
}
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffled() -> [Element] {
var list = Array(self)
list.shuffle()
return list
}
}
The changes are:
The constraint Indices.Iterator.Element == Index is now part
of the Collection protocol, and need not be imposed on the
extension anymore.
Exchanging elements must done by calling swapAt() on the collection,
compare SE-0173 Add MutableCollection.swapAt(_:_:).
Element is an alias for Iterator.Element.
Swift 4
Shuffle the elements of an array in a for loop where i is the mixing ratio
var cards = [Int]() //Some Array
let i = 4 // is the mixing ratio
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: Int(arc4random_uniform(UInt32(cards.count))))
cards.insert(card, at: Int(arc4random_uniform(UInt32(cards.count))))
}
}
Or with extension Int
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: cards.count.arc4random)
cards.insert(card, at: cards.count.arc4random)
}
}
extension Int {
var arc4random: Int {
if self > 0 {
print("Arc for random positiv self \(Int(arc4random_uniform(UInt32(self))))")
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
print("Arc for random negotiv self \(-Int(arc4random_uniform(UInt32(abs(self)))))")
return -Int(arc4random_uniform(UInt32(abs(self))))
} else {
print("Arc for random equal 0")
return 0
}
}
}
This is what I use:
func newShuffledArray(array:NSArray) -> NSArray {
var mutableArray = array.mutableCopy() as! NSMutableArray
var count = mutableArray.count
if count>1 {
for var i=count-1;i>0;--i{
mutableArray.exchangeObjectAtIndex(i, withObjectAtIndex: Int(arc4random_uniform(UInt32(i+1))))
}
}
return mutableArray as NSArray
}
Swift 3 solution, following #Nate Cook answer: (work if the index starts with 0, see comments below)
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffle() -> [Generator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
} }
extension MutableCollection 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 }
let countInt = count as! Int
for i in 0..<countInt - 1 {
let j = Int(arc4random_uniform(UInt32(countInt - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}
This is how its done in a Simplest way.import Gamplaykit to your VC and use the below code. Tested in Xcode 8.
import GameplayKit
let array: NSArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
override func viewDidLoad() {
super.viewDidLoad()
print(array.shuffled())
}
If you want to get a shuffled String from an Array you can use below code..
func suffleString() {
let ShuffleArray = array.shuffled()
suffleString.text = ShuffleArray.first as? String
print(suffleString.text!)
}
With Swift 3, if you want to shuffle an array in place or get a new shuffled array from an array, AnyIterator can help you. The idea is to create an array of indices from your array, to shuffle those indices with an AnyIterator instance and swap(_:_:) function and to map each element of this AnyIterator instance with the array's corresponding element.
The following Playground code shows how it works:
import Darwin // required for arc4random_uniform
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
var indexArray = Array(array.indices)
var index = indexArray.endIndex
let indexIterator: AnyIterator<Int> = AnyIterator {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
let newArray = indexIterator.map { array[$0] }
print(newArray) // may print: ["Jock", "Ellie", "Sue Ellen", "JR", "Pamela", "Bobby"]
You can refactor the previous code and create a shuffled() function inside an Array extension in order to get a new shuffled array from an array:
import Darwin // required for arc4random_uniform
extension Array {
func shuffled() -> Array<Element> {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
return indexIterator.map { self[$0] }
}
}
Usage:
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
let newArray = array.shuffled()
print(newArray) // may print: ["Bobby", "Pamela", "Jock", "Ellie", "JR", "Sue Ellen"]
let emptyArray = [String]()
let newEmptyArray = emptyArray.shuffled()
print(newEmptyArray) // prints: []
As an alternative to the previous code, you can create a shuffle() function inside an Array extension in order to shuffle an array in place:
import Darwin // required for arc4random_uniform
extension Array {
mutating func shuffle() {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
self = indexIterator.map { self[$0] }
}
}
Usage:
var mutatingArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen", "Pamela", "Jock", "Ellie", "Bobby", "JR"]
In Swift 4.2, there is now a method for both a mutable shuffle and immutable shuffled. You can read more about the random generation and array stuff here.
You can use generic swap function as well and implement mentioned Fisher-Yates:
for idx in 0..<arr.count {
let rnd = Int(arc4random_uniform(UInt32(idx)))
if rnd != idx {
swap(&arr[idx], &arr[rnd])
}
}
or less verbose:
for idx in 0..<steps.count {
swap(&steps[idx], &steps[Int(arc4random_uniform(UInt32(idx)))])
}
works!!. organisms is the array to shuffle.
extension Array
{
/** Randomizes the order of an array's elements. */
mutating func shuffle()
{
for _ in 0..<10
{
sort { (_,_) in arc4random() < arc4random() }
}
}
}
var organisms = [
"ant", "bacteria", "cougar",
"dog", "elephant", "firefly",
"goat", "hedgehog", "iguana"]
print("Original: \(organisms)")
organisms.shuffle()
print("Shuffled: \(organisms)")
Working Array Extension (mutating & non-mutating)
Swift 4.1 / Xcode 9
The top answer is deprecated, so I took it upon myself to create my own extension to shuffle an array in the newest version of Swift, Swift 4.1 (Xcode 9):
extension Array {
// Non-mutating shuffle
var shuffled : Array {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
return shuffledArray
}
// Mutating shuffle
mutating func shuffle() {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
self = shuffledArray
}
}
Call Non-Mutating Shuffle [Array] -> [Array]:
let array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
print(array.shuffled)
This prints array in a random order.
Call Mutating Shuffle [Array] = [Array]:
var array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
array.shuffle()
// The array has now been mutated and contains all of its initial
// values, but in a randomized shuffled order
print(array)
This prints array in its current order, which has already been randomly shuffled.
Hopes this works for everybody, if you have any questions, suggestions, or comments, feel free to ask!
In SWIFT 4
func createShuffledSequenceOfNumbers(max:UInt)->[UInt] {
var array:[UInt]! = []
var myArray:[UInt]! = []
for i in 1...max {
myArray.append(i)
}
for i in 1...max {
array.append(i)
}
var tempArray:[Int]! = []
for index in 0...(myArray.count - 1) {
var isNotFinded:Bool = true
while(isNotFinded){
let randomNumber = arc4random_uniform(UInt32(myArray.count))
let randomIndex = Int(randomNumber)
if(!tempArray.contains(randomIndex)){
tempArray.append(randomIndex)
array[randomIndex] = myArray[index]
isNotFinded = false
}
}
}
return array
}
If you want to use simple Swift For loop function use this ->
var arrayItems = ["A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "X9", "Y10", "Z11"]
var shuffledArray = [String]()
for i in 0..<arrayItems.count
{
let randomObject = Int(arc4random_uniform(UInt32(items.count)))
shuffledArray.append(items[randomObject])
items.remove(at: randomObject)
}
print(shuffledArray)
Swift Array suffle using extension ->
extension Array {
// Order Randomize
mutating func shuffle() {
for _ in 0..<count {
sort { (_,_) in arc4random() < arc4random() }
}
}
}
This is how to shuffle one array with a seed in Swift 3.0.
extension MutableCollection where Indices.Iterator.Element == Index {
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
srand48(seedNumber)
let number:Int = numericCast(unshuffledCount)
let r = floor(drand48() * Double(number))
let d: IndexDistance = numericCast(Int(r))
guard d != 0 else { continue }
let i = index(firstUnshuffled, offsetBy: d)
swap(&self[firstUnshuffled], &self[i])
}
}
}
let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)
This is what I use:
import GameplayKit
extension Collection {
func shuffled() -> [Iterator.Element] {
let shuffledArray = (self as? NSArray)?.shuffled()
let outputArray = shuffledArray as? [Iterator.Element]
return outputArray ?? []
}
mutating func shuffle() {
if let selfShuffled = self.shuffled() as? Self {
self = selfShuffled
}
}
}
// Usage example:
var numbers = [1,2,3,4,5]
numbers.shuffle()
print(numbers) // output example: [2, 3, 5, 4, 1]
print([10, "hi", 9.0].shuffled()) // output example: [hi, 10, 9]
Simple Example:
extension Array {
mutating func shuffled() {
for _ in self {
// generate random indexes that will be swapped
var (a, b) = (Int(arc4random_uniform(UInt32(self.count - 1))), Int(arc4random_uniform(UInt32(self.count - 1))))
if a == b { // if the same indexes are generated swap the first and last
a = 0
b = self.count - 1
}
swap(&self[a], &self[b])
}
}
}
var array = [1,2,3,4,5,6,7,8,9,10]
array.shuffled()
print(array) // [9, 8, 3, 5, 7, 6, 4, 2, 1, 10]
Here's some code that runs in playground. You won't need to import Darwin in an actual Xcode project.
import darwin
var a = [1,2,3,4,5,6,7]
func shuffle<ItemType>(item1: ItemType, item2: ItemType) -> Bool {
return drand48() > 0.5
}
sort(a, shuffle)
println(a)
It stop at "swap(&self[i], &self[j])" when I upgrade the xCode version to 7.4 beta.
fatal error: swapping a location with itself is not supported
I found the reason that i = j (function of swap will exploded)
So I add a condition as below
if (i != j){
swap(&list[i], &list[j])
}
YA! It's OK for me.
Related
.shuffle() and .shuffled() are part of Swift
Original historic question:
How do I randomize or shuffle the elements within an array in Swift? For example, if my array consists of 52 playing cards, I want to shuffle the array in order to shuffle the deck.
This answer details how to shuffle with a fast and uniform algorithm (Fisher-Yates) in Swift 4.2+ and how to add the same feature in the various previous versions of Swift. The naming and behavior for each Swift version matches the mutating and nonmutating sorting methods for that version.
Swift 4.2+
shuffle and shuffled are native starting Swift 4.2. Example usage:
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 4.0 and 4.1
These extensions add a shuffle() method to any mutable collection (arrays and unsafe mutable buffers) and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 3
These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 2
(obsolete language: you can't use Swift 2.x to publish on iTunes Connect starting July 2018)
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
}
}
Usage:
[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
(obsolete language: you can't use Swift 1.x to publish on iTunes Connect starting July 2018)
shuffle as a mutating array method
This extension will let you shuffle a mutable Array instance in place:
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 as a non-mutating array method
This extension will let you retrieve a shuffled copy of an Array instance:
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]
Edit: As noted in other answers, Swift 4.2 finally adds random number generation to the standard library, complete with array shuffling.
However, the GKRandom / GKRandomDistribution suite in GameplayKit can still be useful with the new RandomNumberGenerator protocol — if you add extensions to the GameplayKit RNGs to conform to the new standard library protocol, you can easily get:
sendable RNGs (that can reproduce a "random" sequence when needed for testing)
RNGs that sacrifice robustness for speed
RNGs that produce non-uniform distributions
...and still make use of the nice new "native" random APIs in Swift.
The rest of this answer concerns such RNGs and/or their use in older Swift compilers.
There are some good answers here already, as well as some good illustrations of why writing your own shuffle can be error-prone if you're not careful.
In iOS 9, macOS 10.11, and tvOS 9 (or later), you don't have to write your own. There's an efficient, correct implementation of Fisher-Yates in GameplayKit (which, despite the name, is not just for games).
If you just want a unique shuffle:
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
If you want to be able to replicate a shuffle or series of shuffles, choose and seed a specific random source; e.g.
let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)
In iOS 10 / macOS 10.12 / tvOS 10, there's also a convenience syntax for shuffling via an extension on NSArray. Of course, that's a little cumbersome when you're using a Swift Array (and it loses its element type on coming back to Swift):
let shuffled1 = (array as NSArray).shuffled(using: random) // -> [Any]
let shuffled2 = (array as NSArray).shuffled() // use default random source
But it's pretty easy to make a type-preserving Swift wrapper for it:
extension Array {
func shuffled(using source: GKRandomSource) -> [Element] {
return (self as NSArray).shuffled(using: source) as! [Element]
}
func shuffled() -> [Element] {
return (self as NSArray).shuffled() as! [Element]
}
}
let shuffled3 = array.shuffled(using: random)
let shuffled4 = array.shuffled()
In Swift 2.0, GameplayKit may come to the rescue! (supported by iOS9 or later)
import GameplayKit
func shuffle() {
array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}
Here's something possibly a little shorter:
sorted(a) {_, _ in arc4random() % 2 == 0}
Taking Nate's algorithm I wanted to see how this would look with Swift 2 and protocol extensions.
This is what I came up with.
extension MutableCollectionType where Self.Index == Int {
mutating func shuffleInPlace() {
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&self[i], &self[j])
}
}
}
extension MutableCollectionType where Self.Index == Int {
func shuffle() -> Self {
var r = self
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&r[i], &r[j])
}
return r
}
}
Now, any MutableCollectionType can use these methods given it uses Int as an Index
As of swift 4.2 there are two handy functions:
// shuffles the array in place
myArray.shuffle()
and
// generates a new array with shuffled elements of the old array
let newArray = myArray.shuffled()
In my case, I had some problems of swapping objects in Array. Then I scratched my head and went for reinventing the wheel.
// swift 3.0 ready
extension Array {
func shuffled() -> [Element] {
var results = [Element]()
var indexes = (0 ..< count).map { $0 }
while indexes.count > 0 {
let indexOfIndexes = Int(arc4random_uniform(UInt32(indexes.count)))
let index = indexes[indexOfIndexes]
results.append(self[index])
indexes.remove(at: indexOfIndexes)
}
return results
}
}
This is a version of Nate's implementation of the Fisher-Yates shuffle for Swift 4
(Xcode 9).
extension MutableCollection {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
for i in indices.dropLast() {
let diff = distance(from: i, to: endIndex)
let j = index(i, offsetBy: numericCast(arc4random_uniform(numericCast(diff))))
swapAt(i, j)
}
}
}
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffled() -> [Element] {
var list = Array(self)
list.shuffle()
return list
}
}
The changes are:
The constraint Indices.Iterator.Element == Index is now part
of the Collection protocol, and need not be imposed on the
extension anymore.
Exchanging elements must done by calling swapAt() on the collection,
compare SE-0173 Add MutableCollection.swapAt(_:_:).
Element is an alias for Iterator.Element.
Swift 4
Shuffle the elements of an array in a for loop where i is the mixing ratio
var cards = [Int]() //Some Array
let i = 4 // is the mixing ratio
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: Int(arc4random_uniform(UInt32(cards.count))))
cards.insert(card, at: Int(arc4random_uniform(UInt32(cards.count))))
}
}
Or with extension Int
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: cards.count.arc4random)
cards.insert(card, at: cards.count.arc4random)
}
}
extension Int {
var arc4random: Int {
if self > 0 {
print("Arc for random positiv self \(Int(arc4random_uniform(UInt32(self))))")
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
print("Arc for random negotiv self \(-Int(arc4random_uniform(UInt32(abs(self)))))")
return -Int(arc4random_uniform(UInt32(abs(self))))
} else {
print("Arc for random equal 0")
return 0
}
}
}
This is what I use:
func newShuffledArray(array:NSArray) -> NSArray {
var mutableArray = array.mutableCopy() as! NSMutableArray
var count = mutableArray.count
if count>1 {
for var i=count-1;i>0;--i{
mutableArray.exchangeObjectAtIndex(i, withObjectAtIndex: Int(arc4random_uniform(UInt32(i+1))))
}
}
return mutableArray as NSArray
}
Swift 3 solution, following #Nate Cook answer: (work if the index starts with 0, see comments below)
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffle() -> [Generator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
} }
extension MutableCollection 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 }
let countInt = count as! Int
for i in 0..<countInt - 1 {
let j = Int(arc4random_uniform(UInt32(countInt - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}
This is how its done in a Simplest way.import Gamplaykit to your VC and use the below code. Tested in Xcode 8.
import GameplayKit
let array: NSArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
override func viewDidLoad() {
super.viewDidLoad()
print(array.shuffled())
}
If you want to get a shuffled String from an Array you can use below code..
func suffleString() {
let ShuffleArray = array.shuffled()
suffleString.text = ShuffleArray.first as? String
print(suffleString.text!)
}
With Swift 3, if you want to shuffle an array in place or get a new shuffled array from an array, AnyIterator can help you. The idea is to create an array of indices from your array, to shuffle those indices with an AnyIterator instance and swap(_:_:) function and to map each element of this AnyIterator instance with the array's corresponding element.
The following Playground code shows how it works:
import Darwin // required for arc4random_uniform
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
var indexArray = Array(array.indices)
var index = indexArray.endIndex
let indexIterator: AnyIterator<Int> = AnyIterator {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
let newArray = indexIterator.map { array[$0] }
print(newArray) // may print: ["Jock", "Ellie", "Sue Ellen", "JR", "Pamela", "Bobby"]
You can refactor the previous code and create a shuffled() function inside an Array extension in order to get a new shuffled array from an array:
import Darwin // required for arc4random_uniform
extension Array {
func shuffled() -> Array<Element> {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
return indexIterator.map { self[$0] }
}
}
Usage:
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
let newArray = array.shuffled()
print(newArray) // may print: ["Bobby", "Pamela", "Jock", "Ellie", "JR", "Sue Ellen"]
let emptyArray = [String]()
let newEmptyArray = emptyArray.shuffled()
print(newEmptyArray) // prints: []
As an alternative to the previous code, you can create a shuffle() function inside an Array extension in order to shuffle an array in place:
import Darwin // required for arc4random_uniform
extension Array {
mutating func shuffle() {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
self = indexIterator.map { self[$0] }
}
}
Usage:
var mutatingArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen", "Pamela", "Jock", "Ellie", "Bobby", "JR"]
In Swift 4.2, there is now a method for both a mutable shuffle and immutable shuffled. You can read more about the random generation and array stuff here.
You can use generic swap function as well and implement mentioned Fisher-Yates:
for idx in 0..<arr.count {
let rnd = Int(arc4random_uniform(UInt32(idx)))
if rnd != idx {
swap(&arr[idx], &arr[rnd])
}
}
or less verbose:
for idx in 0..<steps.count {
swap(&steps[idx], &steps[Int(arc4random_uniform(UInt32(idx)))])
}
works!!. organisms is the array to shuffle.
extension Array
{
/** Randomizes the order of an array's elements. */
mutating func shuffle()
{
for _ in 0..<10
{
sort { (_,_) in arc4random() < arc4random() }
}
}
}
var organisms = [
"ant", "bacteria", "cougar",
"dog", "elephant", "firefly",
"goat", "hedgehog", "iguana"]
print("Original: \(organisms)")
organisms.shuffle()
print("Shuffled: \(organisms)")
Working Array Extension (mutating & non-mutating)
Swift 4.1 / Xcode 9
The top answer is deprecated, so I took it upon myself to create my own extension to shuffle an array in the newest version of Swift, Swift 4.1 (Xcode 9):
extension Array {
// Non-mutating shuffle
var shuffled : Array {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
return shuffledArray
}
// Mutating shuffle
mutating func shuffle() {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
self = shuffledArray
}
}
Call Non-Mutating Shuffle [Array] -> [Array]:
let array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
print(array.shuffled)
This prints array in a random order.
Call Mutating Shuffle [Array] = [Array]:
var array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
array.shuffle()
// The array has now been mutated and contains all of its initial
// values, but in a randomized shuffled order
print(array)
This prints array in its current order, which has already been randomly shuffled.
Hopes this works for everybody, if you have any questions, suggestions, or comments, feel free to ask!
In SWIFT 4
func createShuffledSequenceOfNumbers(max:UInt)->[UInt] {
var array:[UInt]! = []
var myArray:[UInt]! = []
for i in 1...max {
myArray.append(i)
}
for i in 1...max {
array.append(i)
}
var tempArray:[Int]! = []
for index in 0...(myArray.count - 1) {
var isNotFinded:Bool = true
while(isNotFinded){
let randomNumber = arc4random_uniform(UInt32(myArray.count))
let randomIndex = Int(randomNumber)
if(!tempArray.contains(randomIndex)){
tempArray.append(randomIndex)
array[randomIndex] = myArray[index]
isNotFinded = false
}
}
}
return array
}
If you want to use simple Swift For loop function use this ->
var arrayItems = ["A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "X9", "Y10", "Z11"]
var shuffledArray = [String]()
for i in 0..<arrayItems.count
{
let randomObject = Int(arc4random_uniform(UInt32(items.count)))
shuffledArray.append(items[randomObject])
items.remove(at: randomObject)
}
print(shuffledArray)
Swift Array suffle using extension ->
extension Array {
// Order Randomize
mutating func shuffle() {
for _ in 0..<count {
sort { (_,_) in arc4random() < arc4random() }
}
}
}
This is how to shuffle one array with a seed in Swift 3.0.
extension MutableCollection where Indices.Iterator.Element == Index {
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
srand48(seedNumber)
let number:Int = numericCast(unshuffledCount)
let r = floor(drand48() * Double(number))
let d: IndexDistance = numericCast(Int(r))
guard d != 0 else { continue }
let i = index(firstUnshuffled, offsetBy: d)
swap(&self[firstUnshuffled], &self[i])
}
}
}
let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)
This is what I use:
import GameplayKit
extension Collection {
func shuffled() -> [Iterator.Element] {
let shuffledArray = (self as? NSArray)?.shuffled()
let outputArray = shuffledArray as? [Iterator.Element]
return outputArray ?? []
}
mutating func shuffle() {
if let selfShuffled = self.shuffled() as? Self {
self = selfShuffled
}
}
}
// Usage example:
var numbers = [1,2,3,4,5]
numbers.shuffle()
print(numbers) // output example: [2, 3, 5, 4, 1]
print([10, "hi", 9.0].shuffled()) // output example: [hi, 10, 9]
Simple Example:
extension Array {
mutating func shuffled() {
for _ in self {
// generate random indexes that will be swapped
var (a, b) = (Int(arc4random_uniform(UInt32(self.count - 1))), Int(arc4random_uniform(UInt32(self.count - 1))))
if a == b { // if the same indexes are generated swap the first and last
a = 0
b = self.count - 1
}
swap(&self[a], &self[b])
}
}
}
var array = [1,2,3,4,5,6,7,8,9,10]
array.shuffled()
print(array) // [9, 8, 3, 5, 7, 6, 4, 2, 1, 10]
Here's some code that runs in playground. You won't need to import Darwin in an actual Xcode project.
import darwin
var a = [1,2,3,4,5,6,7]
func shuffle<ItemType>(item1: ItemType, item2: ItemType) -> Bool {
return drand48() > 0.5
}
sort(a, shuffle)
println(a)
It stop at "swap(&self[i], &self[j])" when I upgrade the xCode version to 7.4 beta.
fatal error: swapping a location with itself is not supported
I found the reason that i = j (function of swap will exploded)
So I add a condition as below
if (i != j){
swap(&list[i], &list[j])
}
YA! It's OK for me.
I'm trying to convert the below Swift 2 extension method to Swift 3.
extension CollectionType {
func chunk(withDistance distance: Index.Distance) -> [[SubSequence.Generator.Element]] {
var index = startIndex
let generator: AnyGenerator<Array<SubSequence.Generator.Element>> = anyGenerator {
defer { index = index.advancedBy(distance, limit: self.endIndex) }
return index != self.endIndex ? Array(self[index ..< index.advancedBy(distance, limit: self.endIndex)]) : nil
}
return Array(generator)
}
}
The Xcode conversion tool left me with this.
extension Collection {
func chunk(withDistance distance: Int) -> [[SubSequence.Iterator.Element]] {
var index = startIndex
let generator: AnyGenerator<Array<SubSequence.Generator.Element>> = anyGenerator {
defer { index = index.advancedBy(distance, limit: self.endIndex) }
return index != self.endIndex ? Array(self[index ..< index.advancedBy(distance, limit: self.endIndex)]) : nil
}
return Array(generator)
}
}
Now I'm getting the above error at line, let generator: AnyGenerator<Array<SubSequence.Generator.Element>> = anyGenerator {. I can't figure out how to fix this.
There are several problems:
Generator has been renamed to Iterator in Swift 3, and consequently
AnyGenerator to AnyIterator.
IndexDistance is the associated type of Collection which
represents the number of steps between indices.
In Swift 3, "Collections move their index", see
A New Model for Collections and Indices on Swift evolution.
Putting it all together, your method could look in Swift 3 like this:
extension Collection {
func chunk(withDistance distance: IndexDistance) -> [[SubSequence.Iterator.Element]] {
var pos = startIndex
let iterator: AnyIterator<Array<SubSequence.Iterator.Element>> = AnyIterator {
// Already at the end?
if pos == self.endIndex { return nil }
// Compute `pos + distance`, but not beyond `self.endIndex`:
let endPos = self.index(pos, offsetBy: distance, limitedBy: self.endIndex) ?? self.endIndex
// Return chunk and advance `pos`:
defer { pos = endPos }
return Array(self[pos..<endPos])
}
return Array(iterator)
}
}
let a = [1, 2, 3, 4, 5, 6, 7]
let c = a.chunk(withDistance: 2)
print(c) // [[1, 2], [3, 4], [5, 6], [7]]
I have renamed the local index variable to pos, to avoid
confusion with the
public func index(_ i: Self.Index, offsetBy n: Self.IndexDistance, limitedBy limit: Self.Index) -> Self.Index?
method of Collection which is used to advance the index.
Of course you could achieve the same result with a while loop
instead of an Iterator:
extension Collection {
func chunk(withDistance distance: IndexDistance) -> [[SubSequence.Iterator.Element]] {
var result: [[SubSequence.Iterator.Element]] = []
var pos = startIndex
while pos != endIndex {
let endPos = self.index(pos, offsetBy: distance, limitedBy: self.endIndex) ?? self.endIndex
result.append(Array(self[pos..<endPos]))
pos = endPos
}
return result
}
}
.shuffle() and .shuffled() are part of Swift
Original historic question:
How do I randomize or shuffle the elements within an array in Swift? For example, if my array consists of 52 playing cards, I want to shuffle the array in order to shuffle the deck.
This answer details how to shuffle with a fast and uniform algorithm (Fisher-Yates) in Swift 4.2+ and how to add the same feature in the various previous versions of Swift. The naming and behavior for each Swift version matches the mutating and nonmutating sorting methods for that version.
Swift 4.2+
shuffle and shuffled are native starting Swift 4.2. Example usage:
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 4.0 and 4.1
These extensions add a shuffle() method to any mutable collection (arrays and unsafe mutable buffers) and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 3
These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 2
(obsolete language: you can't use Swift 2.x to publish on iTunes Connect starting July 2018)
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
}
}
Usage:
[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
(obsolete language: you can't use Swift 1.x to publish on iTunes Connect starting July 2018)
shuffle as a mutating array method
This extension will let you shuffle a mutable Array instance in place:
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 as a non-mutating array method
This extension will let you retrieve a shuffled copy of an Array instance:
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]
Edit: As noted in other answers, Swift 4.2 finally adds random number generation to the standard library, complete with array shuffling.
However, the GKRandom / GKRandomDistribution suite in GameplayKit can still be useful with the new RandomNumberGenerator protocol — if you add extensions to the GameplayKit RNGs to conform to the new standard library protocol, you can easily get:
sendable RNGs (that can reproduce a "random" sequence when needed for testing)
RNGs that sacrifice robustness for speed
RNGs that produce non-uniform distributions
...and still make use of the nice new "native" random APIs in Swift.
The rest of this answer concerns such RNGs and/or their use in older Swift compilers.
There are some good answers here already, as well as some good illustrations of why writing your own shuffle can be error-prone if you're not careful.
In iOS 9, macOS 10.11, and tvOS 9 (or later), you don't have to write your own. There's an efficient, correct implementation of Fisher-Yates in GameplayKit (which, despite the name, is not just for games).
If you just want a unique shuffle:
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
If you want to be able to replicate a shuffle or series of shuffles, choose and seed a specific random source; e.g.
let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)
In iOS 10 / macOS 10.12 / tvOS 10, there's also a convenience syntax for shuffling via an extension on NSArray. Of course, that's a little cumbersome when you're using a Swift Array (and it loses its element type on coming back to Swift):
let shuffled1 = (array as NSArray).shuffled(using: random) // -> [Any]
let shuffled2 = (array as NSArray).shuffled() // use default random source
But it's pretty easy to make a type-preserving Swift wrapper for it:
extension Array {
func shuffled(using source: GKRandomSource) -> [Element] {
return (self as NSArray).shuffled(using: source) as! [Element]
}
func shuffled() -> [Element] {
return (self as NSArray).shuffled() as! [Element]
}
}
let shuffled3 = array.shuffled(using: random)
let shuffled4 = array.shuffled()
In Swift 2.0, GameplayKit may come to the rescue! (supported by iOS9 or later)
import GameplayKit
func shuffle() {
array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}
Here's something possibly a little shorter:
sorted(a) {_, _ in arc4random() % 2 == 0}
Taking Nate's algorithm I wanted to see how this would look with Swift 2 and protocol extensions.
This is what I came up with.
extension MutableCollectionType where Self.Index == Int {
mutating func shuffleInPlace() {
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&self[i], &self[j])
}
}
}
extension MutableCollectionType where Self.Index == Int {
func shuffle() -> Self {
var r = self
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&r[i], &r[j])
}
return r
}
}
Now, any MutableCollectionType can use these methods given it uses Int as an Index
As of swift 4.2 there are two handy functions:
// shuffles the array in place
myArray.shuffle()
and
// generates a new array with shuffled elements of the old array
let newArray = myArray.shuffled()
In my case, I had some problems of swapping objects in Array. Then I scratched my head and went for reinventing the wheel.
// swift 3.0 ready
extension Array {
func shuffled() -> [Element] {
var results = [Element]()
var indexes = (0 ..< count).map { $0 }
while indexes.count > 0 {
let indexOfIndexes = Int(arc4random_uniform(UInt32(indexes.count)))
let index = indexes[indexOfIndexes]
results.append(self[index])
indexes.remove(at: indexOfIndexes)
}
return results
}
}
This is a version of Nate's implementation of the Fisher-Yates shuffle for Swift 4
(Xcode 9).
extension MutableCollection {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
for i in indices.dropLast() {
let diff = distance(from: i, to: endIndex)
let j = index(i, offsetBy: numericCast(arc4random_uniform(numericCast(diff))))
swapAt(i, j)
}
}
}
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffled() -> [Element] {
var list = Array(self)
list.shuffle()
return list
}
}
The changes are:
The constraint Indices.Iterator.Element == Index is now part
of the Collection protocol, and need not be imposed on the
extension anymore.
Exchanging elements must done by calling swapAt() on the collection,
compare SE-0173 Add MutableCollection.swapAt(_:_:).
Element is an alias for Iterator.Element.
Swift 4
Shuffle the elements of an array in a for loop where i is the mixing ratio
var cards = [Int]() //Some Array
let i = 4 // is the mixing ratio
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: Int(arc4random_uniform(UInt32(cards.count))))
cards.insert(card, at: Int(arc4random_uniform(UInt32(cards.count))))
}
}
Or with extension Int
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: cards.count.arc4random)
cards.insert(card, at: cards.count.arc4random)
}
}
extension Int {
var arc4random: Int {
if self > 0 {
print("Arc for random positiv self \(Int(arc4random_uniform(UInt32(self))))")
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
print("Arc for random negotiv self \(-Int(arc4random_uniform(UInt32(abs(self)))))")
return -Int(arc4random_uniform(UInt32(abs(self))))
} else {
print("Arc for random equal 0")
return 0
}
}
}
This is what I use:
func newShuffledArray(array:NSArray) -> NSArray {
var mutableArray = array.mutableCopy() as! NSMutableArray
var count = mutableArray.count
if count>1 {
for var i=count-1;i>0;--i{
mutableArray.exchangeObjectAtIndex(i, withObjectAtIndex: Int(arc4random_uniform(UInt32(i+1))))
}
}
return mutableArray as NSArray
}
Swift 3 solution, following #Nate Cook answer: (work if the index starts with 0, see comments below)
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffle() -> [Generator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
} }
extension MutableCollection 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 }
let countInt = count as! Int
for i in 0..<countInt - 1 {
let j = Int(arc4random_uniform(UInt32(countInt - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}
This is how its done in a Simplest way.import Gamplaykit to your VC and use the below code. Tested in Xcode 8.
import GameplayKit
let array: NSArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
override func viewDidLoad() {
super.viewDidLoad()
print(array.shuffled())
}
If you want to get a shuffled String from an Array you can use below code..
func suffleString() {
let ShuffleArray = array.shuffled()
suffleString.text = ShuffleArray.first as? String
print(suffleString.text!)
}
With Swift 3, if you want to shuffle an array in place or get a new shuffled array from an array, AnyIterator can help you. The idea is to create an array of indices from your array, to shuffle those indices with an AnyIterator instance and swap(_:_:) function and to map each element of this AnyIterator instance with the array's corresponding element.
The following Playground code shows how it works:
import Darwin // required for arc4random_uniform
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
var indexArray = Array(array.indices)
var index = indexArray.endIndex
let indexIterator: AnyIterator<Int> = AnyIterator {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
let newArray = indexIterator.map { array[$0] }
print(newArray) // may print: ["Jock", "Ellie", "Sue Ellen", "JR", "Pamela", "Bobby"]
You can refactor the previous code and create a shuffled() function inside an Array extension in order to get a new shuffled array from an array:
import Darwin // required for arc4random_uniform
extension Array {
func shuffled() -> Array<Element> {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
return indexIterator.map { self[$0] }
}
}
Usage:
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
let newArray = array.shuffled()
print(newArray) // may print: ["Bobby", "Pamela", "Jock", "Ellie", "JR", "Sue Ellen"]
let emptyArray = [String]()
let newEmptyArray = emptyArray.shuffled()
print(newEmptyArray) // prints: []
As an alternative to the previous code, you can create a shuffle() function inside an Array extension in order to shuffle an array in place:
import Darwin // required for arc4random_uniform
extension Array {
mutating func shuffle() {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
self = indexIterator.map { self[$0] }
}
}
Usage:
var mutatingArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen", "Pamela", "Jock", "Ellie", "Bobby", "JR"]
In Swift 4.2, there is now a method for both a mutable shuffle and immutable shuffled. You can read more about the random generation and array stuff here.
You can use generic swap function as well and implement mentioned Fisher-Yates:
for idx in 0..<arr.count {
let rnd = Int(arc4random_uniform(UInt32(idx)))
if rnd != idx {
swap(&arr[idx], &arr[rnd])
}
}
or less verbose:
for idx in 0..<steps.count {
swap(&steps[idx], &steps[Int(arc4random_uniform(UInt32(idx)))])
}
works!!. organisms is the array to shuffle.
extension Array
{
/** Randomizes the order of an array's elements. */
mutating func shuffle()
{
for _ in 0..<10
{
sort { (_,_) in arc4random() < arc4random() }
}
}
}
var organisms = [
"ant", "bacteria", "cougar",
"dog", "elephant", "firefly",
"goat", "hedgehog", "iguana"]
print("Original: \(organisms)")
organisms.shuffle()
print("Shuffled: \(organisms)")
Working Array Extension (mutating & non-mutating)
Swift 4.1 / Xcode 9
The top answer is deprecated, so I took it upon myself to create my own extension to shuffle an array in the newest version of Swift, Swift 4.1 (Xcode 9):
extension Array {
// Non-mutating shuffle
var shuffled : Array {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
return shuffledArray
}
// Mutating shuffle
mutating func shuffle() {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
self = shuffledArray
}
}
Call Non-Mutating Shuffle [Array] -> [Array]:
let array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
print(array.shuffled)
This prints array in a random order.
Call Mutating Shuffle [Array] = [Array]:
var array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
array.shuffle()
// The array has now been mutated and contains all of its initial
// values, but in a randomized shuffled order
print(array)
This prints array in its current order, which has already been randomly shuffled.
Hopes this works for everybody, if you have any questions, suggestions, or comments, feel free to ask!
In SWIFT 4
func createShuffledSequenceOfNumbers(max:UInt)->[UInt] {
var array:[UInt]! = []
var myArray:[UInt]! = []
for i in 1...max {
myArray.append(i)
}
for i in 1...max {
array.append(i)
}
var tempArray:[Int]! = []
for index in 0...(myArray.count - 1) {
var isNotFinded:Bool = true
while(isNotFinded){
let randomNumber = arc4random_uniform(UInt32(myArray.count))
let randomIndex = Int(randomNumber)
if(!tempArray.contains(randomIndex)){
tempArray.append(randomIndex)
array[randomIndex] = myArray[index]
isNotFinded = false
}
}
}
return array
}
If you want to use simple Swift For loop function use this ->
var arrayItems = ["A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "X9", "Y10", "Z11"]
var shuffledArray = [String]()
for i in 0..<arrayItems.count
{
let randomObject = Int(arc4random_uniform(UInt32(items.count)))
shuffledArray.append(items[randomObject])
items.remove(at: randomObject)
}
print(shuffledArray)
Swift Array suffle using extension ->
extension Array {
// Order Randomize
mutating func shuffle() {
for _ in 0..<count {
sort { (_,_) in arc4random() < arc4random() }
}
}
}
This is how to shuffle one array with a seed in Swift 3.0.
extension MutableCollection where Indices.Iterator.Element == Index {
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
srand48(seedNumber)
let number:Int = numericCast(unshuffledCount)
let r = floor(drand48() * Double(number))
let d: IndexDistance = numericCast(Int(r))
guard d != 0 else { continue }
let i = index(firstUnshuffled, offsetBy: d)
swap(&self[firstUnshuffled], &self[i])
}
}
}
let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)
This is what I use:
import GameplayKit
extension Collection {
func shuffled() -> [Iterator.Element] {
let shuffledArray = (self as? NSArray)?.shuffled()
let outputArray = shuffledArray as? [Iterator.Element]
return outputArray ?? []
}
mutating func shuffle() {
if let selfShuffled = self.shuffled() as? Self {
self = selfShuffled
}
}
}
// Usage example:
var numbers = [1,2,3,4,5]
numbers.shuffle()
print(numbers) // output example: [2, 3, 5, 4, 1]
print([10, "hi", 9.0].shuffled()) // output example: [hi, 10, 9]
Simple Example:
extension Array {
mutating func shuffled() {
for _ in self {
// generate random indexes that will be swapped
var (a, b) = (Int(arc4random_uniform(UInt32(self.count - 1))), Int(arc4random_uniform(UInt32(self.count - 1))))
if a == b { // if the same indexes are generated swap the first and last
a = 0
b = self.count - 1
}
swap(&self[a], &self[b])
}
}
}
var array = [1,2,3,4,5,6,7,8,9,10]
array.shuffled()
print(array) // [9, 8, 3, 5, 7, 6, 4, 2, 1, 10]
Here's some code that runs in playground. You won't need to import Darwin in an actual Xcode project.
import darwin
var a = [1,2,3,4,5,6,7]
func shuffle<ItemType>(item1: ItemType, item2: ItemType) -> Bool {
return drand48() > 0.5
}
sort(a, shuffle)
println(a)
It stop at "swap(&self[i], &self[j])" when I upgrade the xCode version to 7.4 beta.
fatal error: swapping a location with itself is not supported
I found the reason that i = j (function of swap will exploded)
So I add a condition as below
if (i != j){
swap(&list[i], &list[j])
}
YA! It's OK for me.
.shuffle() and .shuffled() are part of Swift
Original historic question:
How do I randomize or shuffle the elements within an array in Swift? For example, if my array consists of 52 playing cards, I want to shuffle the array in order to shuffle the deck.
This answer details how to shuffle with a fast and uniform algorithm (Fisher-Yates) in Swift 4.2+ and how to add the same feature in the various previous versions of Swift. The naming and behavior for each Swift version matches the mutating and nonmutating sorting methods for that version.
Swift 4.2+
shuffle and shuffled are native starting Swift 4.2. Example usage:
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 4.0 and 4.1
These extensions add a shuffle() method to any mutable collection (arrays and unsafe mutable buffers) and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 3
These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 2
(obsolete language: you can't use Swift 2.x to publish on iTunes Connect starting July 2018)
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
}
}
Usage:
[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
(obsolete language: you can't use Swift 1.x to publish on iTunes Connect starting July 2018)
shuffle as a mutating array method
This extension will let you shuffle a mutable Array instance in place:
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 as a non-mutating array method
This extension will let you retrieve a shuffled copy of an Array instance:
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]
Edit: As noted in other answers, Swift 4.2 finally adds random number generation to the standard library, complete with array shuffling.
However, the GKRandom / GKRandomDistribution suite in GameplayKit can still be useful with the new RandomNumberGenerator protocol — if you add extensions to the GameplayKit RNGs to conform to the new standard library protocol, you can easily get:
sendable RNGs (that can reproduce a "random" sequence when needed for testing)
RNGs that sacrifice robustness for speed
RNGs that produce non-uniform distributions
...and still make use of the nice new "native" random APIs in Swift.
The rest of this answer concerns such RNGs and/or their use in older Swift compilers.
There are some good answers here already, as well as some good illustrations of why writing your own shuffle can be error-prone if you're not careful.
In iOS 9, macOS 10.11, and tvOS 9 (or later), you don't have to write your own. There's an efficient, correct implementation of Fisher-Yates in GameplayKit (which, despite the name, is not just for games).
If you just want a unique shuffle:
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
If you want to be able to replicate a shuffle or series of shuffles, choose and seed a specific random source; e.g.
let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)
In iOS 10 / macOS 10.12 / tvOS 10, there's also a convenience syntax for shuffling via an extension on NSArray. Of course, that's a little cumbersome when you're using a Swift Array (and it loses its element type on coming back to Swift):
let shuffled1 = (array as NSArray).shuffled(using: random) // -> [Any]
let shuffled2 = (array as NSArray).shuffled() // use default random source
But it's pretty easy to make a type-preserving Swift wrapper for it:
extension Array {
func shuffled(using source: GKRandomSource) -> [Element] {
return (self as NSArray).shuffled(using: source) as! [Element]
}
func shuffled() -> [Element] {
return (self as NSArray).shuffled() as! [Element]
}
}
let shuffled3 = array.shuffled(using: random)
let shuffled4 = array.shuffled()
In Swift 2.0, GameplayKit may come to the rescue! (supported by iOS9 or later)
import GameplayKit
func shuffle() {
array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}
Here's something possibly a little shorter:
sorted(a) {_, _ in arc4random() % 2 == 0}
Taking Nate's algorithm I wanted to see how this would look with Swift 2 and protocol extensions.
This is what I came up with.
extension MutableCollectionType where Self.Index == Int {
mutating func shuffleInPlace() {
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&self[i], &self[j])
}
}
}
extension MutableCollectionType where Self.Index == Int {
func shuffle() -> Self {
var r = self
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&r[i], &r[j])
}
return r
}
}
Now, any MutableCollectionType can use these methods given it uses Int as an Index
As of swift 4.2 there are two handy functions:
// shuffles the array in place
myArray.shuffle()
and
// generates a new array with shuffled elements of the old array
let newArray = myArray.shuffled()
In my case, I had some problems of swapping objects in Array. Then I scratched my head and went for reinventing the wheel.
// swift 3.0 ready
extension Array {
func shuffled() -> [Element] {
var results = [Element]()
var indexes = (0 ..< count).map { $0 }
while indexes.count > 0 {
let indexOfIndexes = Int(arc4random_uniform(UInt32(indexes.count)))
let index = indexes[indexOfIndexes]
results.append(self[index])
indexes.remove(at: indexOfIndexes)
}
return results
}
}
This is a version of Nate's implementation of the Fisher-Yates shuffle for Swift 4
(Xcode 9).
extension MutableCollection {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
for i in indices.dropLast() {
let diff = distance(from: i, to: endIndex)
let j = index(i, offsetBy: numericCast(arc4random_uniform(numericCast(diff))))
swapAt(i, j)
}
}
}
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffled() -> [Element] {
var list = Array(self)
list.shuffle()
return list
}
}
The changes are:
The constraint Indices.Iterator.Element == Index is now part
of the Collection protocol, and need not be imposed on the
extension anymore.
Exchanging elements must done by calling swapAt() on the collection,
compare SE-0173 Add MutableCollection.swapAt(_:_:).
Element is an alias for Iterator.Element.
Swift 4
Shuffle the elements of an array in a for loop where i is the mixing ratio
var cards = [Int]() //Some Array
let i = 4 // is the mixing ratio
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: Int(arc4random_uniform(UInt32(cards.count))))
cards.insert(card, at: Int(arc4random_uniform(UInt32(cards.count))))
}
}
Or with extension Int
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: cards.count.arc4random)
cards.insert(card, at: cards.count.arc4random)
}
}
extension Int {
var arc4random: Int {
if self > 0 {
print("Arc for random positiv self \(Int(arc4random_uniform(UInt32(self))))")
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
print("Arc for random negotiv self \(-Int(arc4random_uniform(UInt32(abs(self)))))")
return -Int(arc4random_uniform(UInt32(abs(self))))
} else {
print("Arc for random equal 0")
return 0
}
}
}
This is what I use:
func newShuffledArray(array:NSArray) -> NSArray {
var mutableArray = array.mutableCopy() as! NSMutableArray
var count = mutableArray.count
if count>1 {
for var i=count-1;i>0;--i{
mutableArray.exchangeObjectAtIndex(i, withObjectAtIndex: Int(arc4random_uniform(UInt32(i+1))))
}
}
return mutableArray as NSArray
}
Swift 3 solution, following #Nate Cook answer: (work if the index starts with 0, see comments below)
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffle() -> [Generator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
} }
extension MutableCollection 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 }
let countInt = count as! Int
for i in 0..<countInt - 1 {
let j = Int(arc4random_uniform(UInt32(countInt - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}
This is how its done in a Simplest way.import Gamplaykit to your VC and use the below code. Tested in Xcode 8.
import GameplayKit
let array: NSArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
override func viewDidLoad() {
super.viewDidLoad()
print(array.shuffled())
}
If you want to get a shuffled String from an Array you can use below code..
func suffleString() {
let ShuffleArray = array.shuffled()
suffleString.text = ShuffleArray.first as? String
print(suffleString.text!)
}
With Swift 3, if you want to shuffle an array in place or get a new shuffled array from an array, AnyIterator can help you. The idea is to create an array of indices from your array, to shuffle those indices with an AnyIterator instance and swap(_:_:) function and to map each element of this AnyIterator instance with the array's corresponding element.
The following Playground code shows how it works:
import Darwin // required for arc4random_uniform
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
var indexArray = Array(array.indices)
var index = indexArray.endIndex
let indexIterator: AnyIterator<Int> = AnyIterator {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
let newArray = indexIterator.map { array[$0] }
print(newArray) // may print: ["Jock", "Ellie", "Sue Ellen", "JR", "Pamela", "Bobby"]
You can refactor the previous code and create a shuffled() function inside an Array extension in order to get a new shuffled array from an array:
import Darwin // required for arc4random_uniform
extension Array {
func shuffled() -> Array<Element> {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
return indexIterator.map { self[$0] }
}
}
Usage:
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
let newArray = array.shuffled()
print(newArray) // may print: ["Bobby", "Pamela", "Jock", "Ellie", "JR", "Sue Ellen"]
let emptyArray = [String]()
let newEmptyArray = emptyArray.shuffled()
print(newEmptyArray) // prints: []
As an alternative to the previous code, you can create a shuffle() function inside an Array extension in order to shuffle an array in place:
import Darwin // required for arc4random_uniform
extension Array {
mutating func shuffle() {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
self = indexIterator.map { self[$0] }
}
}
Usage:
var mutatingArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen", "Pamela", "Jock", "Ellie", "Bobby", "JR"]
In Swift 4.2, there is now a method for both a mutable shuffle and immutable shuffled. You can read more about the random generation and array stuff here.
You can use generic swap function as well and implement mentioned Fisher-Yates:
for idx in 0..<arr.count {
let rnd = Int(arc4random_uniform(UInt32(idx)))
if rnd != idx {
swap(&arr[idx], &arr[rnd])
}
}
or less verbose:
for idx in 0..<steps.count {
swap(&steps[idx], &steps[Int(arc4random_uniform(UInt32(idx)))])
}
works!!. organisms is the array to shuffle.
extension Array
{
/** Randomizes the order of an array's elements. */
mutating func shuffle()
{
for _ in 0..<10
{
sort { (_,_) in arc4random() < arc4random() }
}
}
}
var organisms = [
"ant", "bacteria", "cougar",
"dog", "elephant", "firefly",
"goat", "hedgehog", "iguana"]
print("Original: \(organisms)")
organisms.shuffle()
print("Shuffled: \(organisms)")
Working Array Extension (mutating & non-mutating)
Swift 4.1 / Xcode 9
The top answer is deprecated, so I took it upon myself to create my own extension to shuffle an array in the newest version of Swift, Swift 4.1 (Xcode 9):
extension Array {
// Non-mutating shuffle
var shuffled : Array {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
return shuffledArray
}
// Mutating shuffle
mutating func shuffle() {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
self = shuffledArray
}
}
Call Non-Mutating Shuffle [Array] -> [Array]:
let array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
print(array.shuffled)
This prints array in a random order.
Call Mutating Shuffle [Array] = [Array]:
var array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
array.shuffle()
// The array has now been mutated and contains all of its initial
// values, but in a randomized shuffled order
print(array)
This prints array in its current order, which has already been randomly shuffled.
Hopes this works for everybody, if you have any questions, suggestions, or comments, feel free to ask!
In SWIFT 4
func createShuffledSequenceOfNumbers(max:UInt)->[UInt] {
var array:[UInt]! = []
var myArray:[UInt]! = []
for i in 1...max {
myArray.append(i)
}
for i in 1...max {
array.append(i)
}
var tempArray:[Int]! = []
for index in 0...(myArray.count - 1) {
var isNotFinded:Bool = true
while(isNotFinded){
let randomNumber = arc4random_uniform(UInt32(myArray.count))
let randomIndex = Int(randomNumber)
if(!tempArray.contains(randomIndex)){
tempArray.append(randomIndex)
array[randomIndex] = myArray[index]
isNotFinded = false
}
}
}
return array
}
If you want to use simple Swift For loop function use this ->
var arrayItems = ["A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "X9", "Y10", "Z11"]
var shuffledArray = [String]()
for i in 0..<arrayItems.count
{
let randomObject = Int(arc4random_uniform(UInt32(items.count)))
shuffledArray.append(items[randomObject])
items.remove(at: randomObject)
}
print(shuffledArray)
Swift Array suffle using extension ->
extension Array {
// Order Randomize
mutating func shuffle() {
for _ in 0..<count {
sort { (_,_) in arc4random() < arc4random() }
}
}
}
This is how to shuffle one array with a seed in Swift 3.0.
extension MutableCollection where Indices.Iterator.Element == Index {
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
srand48(seedNumber)
let number:Int = numericCast(unshuffledCount)
let r = floor(drand48() * Double(number))
let d: IndexDistance = numericCast(Int(r))
guard d != 0 else { continue }
let i = index(firstUnshuffled, offsetBy: d)
swap(&self[firstUnshuffled], &self[i])
}
}
}
let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)
This is what I use:
import GameplayKit
extension Collection {
func shuffled() -> [Iterator.Element] {
let shuffledArray = (self as? NSArray)?.shuffled()
let outputArray = shuffledArray as? [Iterator.Element]
return outputArray ?? []
}
mutating func shuffle() {
if let selfShuffled = self.shuffled() as? Self {
self = selfShuffled
}
}
}
// Usage example:
var numbers = [1,2,3,4,5]
numbers.shuffle()
print(numbers) // output example: [2, 3, 5, 4, 1]
print([10, "hi", 9.0].shuffled()) // output example: [hi, 10, 9]
Simple Example:
extension Array {
mutating func shuffled() {
for _ in self {
// generate random indexes that will be swapped
var (a, b) = (Int(arc4random_uniform(UInt32(self.count - 1))), Int(arc4random_uniform(UInt32(self.count - 1))))
if a == b { // if the same indexes are generated swap the first and last
a = 0
b = self.count - 1
}
swap(&self[a], &self[b])
}
}
}
var array = [1,2,3,4,5,6,7,8,9,10]
array.shuffled()
print(array) // [9, 8, 3, 5, 7, 6, 4, 2, 1, 10]
Here's some code that runs in playground. You won't need to import Darwin in an actual Xcode project.
import darwin
var a = [1,2,3,4,5,6,7]
func shuffle<ItemType>(item1: ItemType, item2: ItemType) -> Bool {
return drand48() > 0.5
}
sort(a, shuffle)
println(a)
It stop at "swap(&self[i], &self[j])" when I upgrade the xCode version to 7.4 beta.
fatal error: swapping a location with itself is not supported
I found the reason that i = j (function of swap will exploded)
So I add a condition as below
if (i != j){
swap(&list[i], &list[j])
}
YA! It's OK for me.
.shuffle() and .shuffled() are part of Swift
Original historic question:
How do I randomize or shuffle the elements within an array in Swift? For example, if my array consists of 52 playing cards, I want to shuffle the array in order to shuffle the deck.
This answer details how to shuffle with a fast and uniform algorithm (Fisher-Yates) in Swift 4.2+ and how to add the same feature in the various previous versions of Swift. The naming and behavior for each Swift version matches the mutating and nonmutating sorting methods for that version.
Swift 4.2+
shuffle and shuffled are native starting Swift 4.2. Example usage:
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 4.0 and 4.1
These extensions add a shuffle() method to any mutable collection (arrays and unsafe mutable buffers) and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 3
These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence:
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
}
}
Same usage as in Swift 4.2 examples above.
Swift 2
(obsolete language: you can't use Swift 2.x to publish on iTunes Connect starting July 2018)
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
}
}
Usage:
[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
(obsolete language: you can't use Swift 1.x to publish on iTunes Connect starting July 2018)
shuffle as a mutating array method
This extension will let you shuffle a mutable Array instance in place:
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 as a non-mutating array method
This extension will let you retrieve a shuffled copy of an Array instance:
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]
Edit: As noted in other answers, Swift 4.2 finally adds random number generation to the standard library, complete with array shuffling.
However, the GKRandom / GKRandomDistribution suite in GameplayKit can still be useful with the new RandomNumberGenerator protocol — if you add extensions to the GameplayKit RNGs to conform to the new standard library protocol, you can easily get:
sendable RNGs (that can reproduce a "random" sequence when needed for testing)
RNGs that sacrifice robustness for speed
RNGs that produce non-uniform distributions
...and still make use of the nice new "native" random APIs in Swift.
The rest of this answer concerns such RNGs and/or their use in older Swift compilers.
There are some good answers here already, as well as some good illustrations of why writing your own shuffle can be error-prone if you're not careful.
In iOS 9, macOS 10.11, and tvOS 9 (or later), you don't have to write your own. There's an efficient, correct implementation of Fisher-Yates in GameplayKit (which, despite the name, is not just for games).
If you just want a unique shuffle:
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
If you want to be able to replicate a shuffle or series of shuffles, choose and seed a specific random source; e.g.
let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)
In iOS 10 / macOS 10.12 / tvOS 10, there's also a convenience syntax for shuffling via an extension on NSArray. Of course, that's a little cumbersome when you're using a Swift Array (and it loses its element type on coming back to Swift):
let shuffled1 = (array as NSArray).shuffled(using: random) // -> [Any]
let shuffled2 = (array as NSArray).shuffled() // use default random source
But it's pretty easy to make a type-preserving Swift wrapper for it:
extension Array {
func shuffled(using source: GKRandomSource) -> [Element] {
return (self as NSArray).shuffled(using: source) as! [Element]
}
func shuffled() -> [Element] {
return (self as NSArray).shuffled() as! [Element]
}
}
let shuffled3 = array.shuffled(using: random)
let shuffled4 = array.shuffled()
In Swift 2.0, GameplayKit may come to the rescue! (supported by iOS9 or later)
import GameplayKit
func shuffle() {
array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}
Here's something possibly a little shorter:
sorted(a) {_, _ in arc4random() % 2 == 0}
Taking Nate's algorithm I wanted to see how this would look with Swift 2 and protocol extensions.
This is what I came up with.
extension MutableCollectionType where Self.Index == Int {
mutating func shuffleInPlace() {
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&self[i], &self[j])
}
}
}
extension MutableCollectionType where Self.Index == Int {
func shuffle() -> Self {
var r = self
let c = self.count
for i in 0..<(c - 1) {
let j = Int(arc4random_uniform(UInt32(c - i))) + i
swap(&r[i], &r[j])
}
return r
}
}
Now, any MutableCollectionType can use these methods given it uses Int as an Index
As of swift 4.2 there are two handy functions:
// shuffles the array in place
myArray.shuffle()
and
// generates a new array with shuffled elements of the old array
let newArray = myArray.shuffled()
In my case, I had some problems of swapping objects in Array. Then I scratched my head and went for reinventing the wheel.
// swift 3.0 ready
extension Array {
func shuffled() -> [Element] {
var results = [Element]()
var indexes = (0 ..< count).map { $0 }
while indexes.count > 0 {
let indexOfIndexes = Int(arc4random_uniform(UInt32(indexes.count)))
let index = indexes[indexOfIndexes]
results.append(self[index])
indexes.remove(at: indexOfIndexes)
}
return results
}
}
This is a version of Nate's implementation of the Fisher-Yates shuffle for Swift 4
(Xcode 9).
extension MutableCollection {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
for i in indices.dropLast() {
let diff = distance(from: i, to: endIndex)
let j = index(i, offsetBy: numericCast(arc4random_uniform(numericCast(diff))))
swapAt(i, j)
}
}
}
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffled() -> [Element] {
var list = Array(self)
list.shuffle()
return list
}
}
The changes are:
The constraint Indices.Iterator.Element == Index is now part
of the Collection protocol, and need not be imposed on the
extension anymore.
Exchanging elements must done by calling swapAt() on the collection,
compare SE-0173 Add MutableCollection.swapAt(_:_:).
Element is an alias for Iterator.Element.
Swift 4
Shuffle the elements of an array in a for loop where i is the mixing ratio
var cards = [Int]() //Some Array
let i = 4 // is the mixing ratio
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: Int(arc4random_uniform(UInt32(cards.count))))
cards.insert(card, at: Int(arc4random_uniform(UInt32(cards.count))))
}
}
Or with extension Int
func shuffleCards() {
for _ in 0 ..< cards.count * i {
let card = cards.remove(at: cards.count.arc4random)
cards.insert(card, at: cards.count.arc4random)
}
}
extension Int {
var arc4random: Int {
if self > 0 {
print("Arc for random positiv self \(Int(arc4random_uniform(UInt32(self))))")
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
print("Arc for random negotiv self \(-Int(arc4random_uniform(UInt32(abs(self)))))")
return -Int(arc4random_uniform(UInt32(abs(self))))
} else {
print("Arc for random equal 0")
return 0
}
}
}
This is what I use:
func newShuffledArray(array:NSArray) -> NSArray {
var mutableArray = array.mutableCopy() as! NSMutableArray
var count = mutableArray.count
if count>1 {
for var i=count-1;i>0;--i{
mutableArray.exchangeObjectAtIndex(i, withObjectAtIndex: Int(arc4random_uniform(UInt32(i+1))))
}
}
return mutableArray as NSArray
}
Swift 3 solution, following #Nate Cook answer: (work if the index starts with 0, see comments below)
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffle() -> [Generator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
} }
extension MutableCollection 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 }
let countInt = count as! Int
for i in 0..<countInt - 1 {
let j = Int(arc4random_uniform(UInt32(countInt - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}
This is how its done in a Simplest way.import Gamplaykit to your VC and use the below code. Tested in Xcode 8.
import GameplayKit
let array: NSArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
override func viewDidLoad() {
super.viewDidLoad()
print(array.shuffled())
}
If you want to get a shuffled String from an Array you can use below code..
func suffleString() {
let ShuffleArray = array.shuffled()
suffleString.text = ShuffleArray.first as? String
print(suffleString.text!)
}
With Swift 3, if you want to shuffle an array in place or get a new shuffled array from an array, AnyIterator can help you. The idea is to create an array of indices from your array, to shuffle those indices with an AnyIterator instance and swap(_:_:) function and to map each element of this AnyIterator instance with the array's corresponding element.
The following Playground code shows how it works:
import Darwin // required for arc4random_uniform
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
var indexArray = Array(array.indices)
var index = indexArray.endIndex
let indexIterator: AnyIterator<Int> = AnyIterator {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
let newArray = indexIterator.map { array[$0] }
print(newArray) // may print: ["Jock", "Ellie", "Sue Ellen", "JR", "Pamela", "Bobby"]
You can refactor the previous code and create a shuffled() function inside an Array extension in order to get a new shuffled array from an array:
import Darwin // required for arc4random_uniform
extension Array {
func shuffled() -> Array<Element> {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
return indexIterator.map { self[$0] }
}
}
Usage:
let array = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
let newArray = array.shuffled()
print(newArray) // may print: ["Bobby", "Pamela", "Jock", "Ellie", "JR", "Sue Ellen"]
let emptyArray = [String]()
let newEmptyArray = emptyArray.shuffled()
print(newEmptyArray) // prints: []
As an alternative to the previous code, you can create a shuffle() function inside an Array extension in order to shuffle an array in place:
import Darwin // required for arc4random_uniform
extension Array {
mutating func shuffle() {
var indexArray = Array<Int>(indices)
var index = indexArray.endIndex
let indexIterator = AnyIterator<Int> {
guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
else { return nil }
index = nextIndex
let randomIndex = Int(arc4random_uniform(UInt32(index)))
if randomIndex != index {
swap(&indexArray[randomIndex], &indexArray[index])
}
return indexArray[index]
}
self = indexIterator.map { self[$0] }
}
}
Usage:
var mutatingArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen", "Pamela", "Jock", "Ellie", "Bobby", "JR"]
In Swift 4.2, there is now a method for both a mutable shuffle and immutable shuffled. You can read more about the random generation and array stuff here.
You can use generic swap function as well and implement mentioned Fisher-Yates:
for idx in 0..<arr.count {
let rnd = Int(arc4random_uniform(UInt32(idx)))
if rnd != idx {
swap(&arr[idx], &arr[rnd])
}
}
or less verbose:
for idx in 0..<steps.count {
swap(&steps[idx], &steps[Int(arc4random_uniform(UInt32(idx)))])
}
works!!. organisms is the array to shuffle.
extension Array
{
/** Randomizes the order of an array's elements. */
mutating func shuffle()
{
for _ in 0..<10
{
sort { (_,_) in arc4random() < arc4random() }
}
}
}
var organisms = [
"ant", "bacteria", "cougar",
"dog", "elephant", "firefly",
"goat", "hedgehog", "iguana"]
print("Original: \(organisms)")
organisms.shuffle()
print("Shuffled: \(organisms)")
Working Array Extension (mutating & non-mutating)
Swift 4.1 / Xcode 9
The top answer is deprecated, so I took it upon myself to create my own extension to shuffle an array in the newest version of Swift, Swift 4.1 (Xcode 9):
extension Array {
// Non-mutating shuffle
var shuffled : Array {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
return shuffledArray
}
// Mutating shuffle
mutating func shuffle() {
let totalCount : Int = self.count
var shuffledArray : Array = []
var count : Int = totalCount
var tempArray : Array = self
for _ in 0..<totalCount {
let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
let randomElement : Element = tempArray.remove(at: randomIndex)
shuffledArray.append(randomElement)
count -= 1
}
self = shuffledArray
}
}
Call Non-Mutating Shuffle [Array] -> [Array]:
let array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
print(array.shuffled)
This prints array in a random order.
Call Mutating Shuffle [Array] = [Array]:
var array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
array.shuffle()
// The array has now been mutated and contains all of its initial
// values, but in a randomized shuffled order
print(array)
This prints array in its current order, which has already been randomly shuffled.
Hopes this works for everybody, if you have any questions, suggestions, or comments, feel free to ask!
In SWIFT 4
func createShuffledSequenceOfNumbers(max:UInt)->[UInt] {
var array:[UInt]! = []
var myArray:[UInt]! = []
for i in 1...max {
myArray.append(i)
}
for i in 1...max {
array.append(i)
}
var tempArray:[Int]! = []
for index in 0...(myArray.count - 1) {
var isNotFinded:Bool = true
while(isNotFinded){
let randomNumber = arc4random_uniform(UInt32(myArray.count))
let randomIndex = Int(randomNumber)
if(!tempArray.contains(randomIndex)){
tempArray.append(randomIndex)
array[randomIndex] = myArray[index]
isNotFinded = false
}
}
}
return array
}
If you want to use simple Swift For loop function use this ->
var arrayItems = ["A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "X9", "Y10", "Z11"]
var shuffledArray = [String]()
for i in 0..<arrayItems.count
{
let randomObject = Int(arc4random_uniform(UInt32(items.count)))
shuffledArray.append(items[randomObject])
items.remove(at: randomObject)
}
print(shuffledArray)
Swift Array suffle using extension ->
extension Array {
// Order Randomize
mutating func shuffle() {
for _ in 0..<count {
sort { (_,_) in arc4random() < arc4random() }
}
}
}
This is how to shuffle one array with a seed in Swift 3.0.
extension MutableCollection where Indices.Iterator.Element == Index {
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
srand48(seedNumber)
let number:Int = numericCast(unshuffledCount)
let r = floor(drand48() * Double(number))
let d: IndexDistance = numericCast(Int(r))
guard d != 0 else { continue }
let i = index(firstUnshuffled, offsetBy: d)
swap(&self[firstUnshuffled], &self[i])
}
}
}
let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)
This is what I use:
import GameplayKit
extension Collection {
func shuffled() -> [Iterator.Element] {
let shuffledArray = (self as? NSArray)?.shuffled()
let outputArray = shuffledArray as? [Iterator.Element]
return outputArray ?? []
}
mutating func shuffle() {
if let selfShuffled = self.shuffled() as? Self {
self = selfShuffled
}
}
}
// Usage example:
var numbers = [1,2,3,4,5]
numbers.shuffle()
print(numbers) // output example: [2, 3, 5, 4, 1]
print([10, "hi", 9.0].shuffled()) // output example: [hi, 10, 9]
Simple Example:
extension Array {
mutating func shuffled() {
for _ in self {
// generate random indexes that will be swapped
var (a, b) = (Int(arc4random_uniform(UInt32(self.count - 1))), Int(arc4random_uniform(UInt32(self.count - 1))))
if a == b { // if the same indexes are generated swap the first and last
a = 0
b = self.count - 1
}
swap(&self[a], &self[b])
}
}
}
var array = [1,2,3,4,5,6,7,8,9,10]
array.shuffled()
print(array) // [9, 8, 3, 5, 7, 6, 4, 2, 1, 10]
Here's some code that runs in playground. You won't need to import Darwin in an actual Xcode project.
import darwin
var a = [1,2,3,4,5,6,7]
func shuffle<ItemType>(item1: ItemType, item2: ItemType) -> Bool {
return drand48() > 0.5
}
sort(a, shuffle)
println(a)
It stop at "swap(&self[i], &self[j])" when I upgrade the xCode version to 7.4 beta.
fatal error: swapping a location with itself is not supported
I found the reason that i = j (function of swap will exploded)
So I add a condition as below
if (i != j){
swap(&list[i], &list[j])
}
YA! It's OK for me.