By Michael Patzer


2014-06-03 23:15:08 8 Comments

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.

25 comments

@Rahul Singha Roy 2018-06-27 10:48:13

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() }
        }
    }
}

@Maksim Kniazev 2018-09-15 00:46:09

nice way, tried on deck of cards, does not shuffle good

@rickster 2015-06-16 03:37:08

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()

@Richard Venable 2015-10-26 15:02:29

Makes me wonder what other helpful utilities can be found in GameplayKit that I have never explored!

@rickster 2015-10-26 15:07:10

Graph search, tree search, rule systems... lots of stuff that's helpful both in game design and otherwise.

@Evan Pon 2016-11-16 21:38:16

In Swift 3/iOS 10, this has been changed to: let shuffled = lcg.arrayByShufflingObjects(in: array)

@Nate Cook 2014-06-04 05:41:13

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]

@Michael Patzer 2014-06-04 20:39:25

Thanks for the quick response!

@Robert Brax 2014-11-06 13:52:49

How would you turn this into an array extension ?

@Nate Cook 2014-11-06 15:59:30

@RobertBrax Good question - updated the answer!

@Robert Brax 2014-11-06 16:36:34

@NateCook thanks, great answer, my extension collection just got bigger

@Airspeed Velocity 2015-04-04 22:07:28

In case you want the function version in Swift 1.2, it needs a bit of updating as countElements is gone, and it’s replacement, count, now returns a T.Index.Distance so the constraint needs to be on C.Index.Distance == Int. This version should work: gist.github.com/airspeedswift/03d07a9dc86fabdc370f

@Fogmeister 2015-05-11 15:10:17

Just being picky here but are your commented sections a result of this actual algorithm? I thought the Fisher Yates shuffle did not allow any object to be in the position it started in and "7" and "goodbye" in your example haven't moved. Or am I not reading the code right? Excellent answer though. I have used it many times. :-D

@Nate Cook 2015-05-11 15:42:47

Those are the actual output—Fisher-Yates should return an unbiased random permutation of the source, so there's no requirement that a particular element should move. There is a guarantee that no element moves more than once, but sometimes the "move" is to the same index. The simplest case is to think about [1, 2].shuffled()—should that return [2, 1] every time?

@Carl Smith 2015-06-30 00:00:26

I added if count > 0 at the top of the mutating array function, to prevent receiving a "fatal error: Can't form Range with end < start" when it is passed an empty array.

@sabiland 2015-07-02 07:48:51

@CarlSmith or list.isEmpty

@Richard Venable 2015-07-09 18:43:19

Your Swift 2.0 shuffle() method always returns an Array, regardless of the CollectionType. Is there not a way to improve it to always return the same CollectionType in Swift 2.0?

@Jan 2015-09-10 03:59:34

swap is giving a runtime error in the latest xcode beta: fatal error: swapping a location with itself is not supported. Any workarounds?

@Nate Cook 2015-09-10 12:40:12

@Jan: Yes, add guard i != j else { continue } before the swap. I filed a radar, but the new behavior is intentional.

@Damo 2015-09-28 16:29:56

added 'import Foundation' so that it works inside a Playground

@Martin R 2016-06-15 19:37:02

For Swift 3, see stackoverflow.com/questions/37843647/shufle-array-swift-3, perhaps you want to add that to your answer.

@Martin R 2016-09-14 12:01:57

Actually shuffleInPlace can crash if the collection indices do not start at zero, e.g. for an array slice. for i in 0..<count - 1 should be for i in startIndex ..< endIndex - 1 (and then the conversion to Swift 3 becomes almost trivial).

@Nate Cook 2016-09-18 20:33:57

@MartinR: Good catch, thank you! Now this works (Swift 2 syntax): var numbers = Array(1...10); number[5..<10].shuffleInPlace()

@onmyway133 2017-06-22 14:28:48

fatal error: swapping a location with itself is not supported

@hkatz 2017-08-25 14:41:16

@NateCook Is there any simple way of modifying this in order to guarantee that NO element remains in its original position following conclusion of the shuffle?

@hkatz 2017-08-26 13:53:42

@NateCook. never mind. I've since learned that the condition I specified above is called a "derangement" of an array (great term!:-), and there are several answers posted on how to do this (although none in swift).

@Hondus 2018-03-30 07:35:15

IndexDistance is deprecated in Swift 4.1

@J.Doe 2018-04-01 16:35:07

This does not work in XCode playgrounds cannot invoke index with an argument list of type self.index, offsetBy: int

@Roi Mulia 2018-04-01 17:23:06

Not working in Swift 4.1

@3366784 2018-04-15 19:34:49

It would have been easier to read if you followed swift naming conventions and didn't use single letter names for variables.

@leogdion 2018-06-05 16:48:19

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.

@ali khezri 2018-05-17 07:52:30

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
}

@Martin R 2017-06-09 07:07:12

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.

@Noah Wilder 2018-03-21 16:14:12

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!

@Sergei 2018-01-03 09:22:32

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
        }
    }
}

@Vimal 2017-12-08 09:49:27

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)")

@Federico Zanetello 2018-05-06 16:48:47

Love the conciseness, thanks!

@Rajamohan S 2017-08-07 06:39:42

Form the article of Fisher–Yates shuffle on Wikipedia

Swift 3.1,4.0

a). Pencil-and-paper method :

func shuffle<T>(_ array:inout [T]){

    var temp = [T]()

    for _  in array{

        /*Generating random number with length*/
        let random = arc4random_uniform(UInt32(array.count))
        /*Take the element from array*/
        let elementTaken = array[Int(random)]
        /*Append it to new tempArray*/
        temp.append(elementTaken)
        /*Remove the element from array*/
        array.remove(at: Int(random))

    }
    /* array = tempArray*/
    array = temp
}

b). Modern method:(Durstenfeld's version)

func shuffle<T>(_ array:inout [T]){

    var length = array.count

    for _  in array{

        /*Generating random number with length*/
        let random = arc4random_uniform(UInt32(length))
        /*Check before index of two elements not same*/
        if length-1 != Int(random){
            swap(&array[length-1], &array[Int(random)])
        }

        length -= 1
    }
}

Extension:

a). Pencil-and-paper method :

extension Array{

    mutating func shuffled(){

        var temp = [Element]()

        for _  in self{

            /*Generating random number with length*/
            let random = arc4random_uniform(UInt32(self.count))
            /*Take the element from array*/
            let elementTaken = self[Int(random)]
            /*Append it to new tempArray*/
            temp.append(elementTaken)
            /*Remove the element from array*/
            self.remove(at: Int(random))

        }
        /* array = tempArray*/
        self = temp
    }
}

b). Modern method:(Durstenfeld's version)

extension Array{

    mutating func shuffled(){

        var length = self.count

        for _  in self{

            /*Generating random number with length*/
            let random = arc4random_uniform(UInt32(length))

            /*Check before index of two elements not same*/

            if length-1 != Int(random){

                /*Swaping elements, If same index then there is no swap*/
               // swap(&self[length-1], &self[Int(random)]) -> Swift 3.0
                self.swapAt(length-1, Int(random)) //-> Swift 4.0

            }

            length -= 1
        }
    }
}

Reference :

/* By using shuffle functions*/
var a = [1,2,3,4,5,6,7,8,9,10]

for _ in 1...10{

    self.shuffle(&a)

    /*For shuffled extension, a.shuffled()*/
    print(a)
}

Note: You can use empty array also.

Output:

[6, 2, 10, 5, 1, 8, 9, 4, 3, 7]

[7, 1, 9, 8, 2, 10, 5, 6, 4, 3]

[8, 9, 6, 10, 5, 2, 7, 4, 3, 1]

[10, 1, 7, 4, 8, 9, 3, 5, 2, 6]

[8, 1, 6, 9, 3, 7, 4, 5, 10, 2]

[4, 3, 7, 9, 1, 5, 8, 6, 10, 2]

[7, 3, 4, 9, 10, 1, 6, 5, 2, 8]

[3, 6, 2, 4, 5, 8, 9, 7, 1, 10]

[5, 1, 2, 10, 6, 9, 7, 3, 8, 4]

[7, 9, 3, 8, 2, 1, 5, 4, 6, 10]

Please let me know if any queries, Other Swift version will be check soon.

@Bobby 2017-07-02 17:34:45

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]

@Daniel Illescas 2017-06-24 20:45:01

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]

@Rohit Sisodia 2017-06-05 09:57:23

let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)

@Imanou Petit 2015-12-15 15:45:12

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"]

@Tayo119 2016-12-15 09:41:43

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])
        }
    }
}

@Joe 2016-10-03 15:02:43

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!)

}

@Kaz Yoshikawa 2016-10-24 04:46:33

In my case, I had some problems of swapping objects in Array. Then I scratched my head and go 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
    }

}

@Anson Yao 2016-08-25 19:35:30

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])
        }
    }
}

@Martin R 2016-09-14 11:55:00

This can crash if the collection indices do start at 0, e.g. for an array slice. Try to run var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace() several times. – See stackoverflow.com/a/37843901/1187415 for a correct solution.

@bluenowhere 2016-03-17 05:53:12

In Swift 2.0, GameplayKit may come to the rescue! (supported by iOS9 or later)

import GameplayKit

func shuffle() {
    array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}

@Lope 2017-04-28 18:08:22

importing GameplayKit just to get shuffled array doesn't sound like a great idea

@Abizern 2017-10-07 04:16:16

Why? It's part of the system, doesn't add to the binary.

@JRG-Developer 2017-11-14 12:56:35

You can also scope the import to simply import GameplayKit.GKRandomSource

@米米米 2015-08-26 03:27:06

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.

@Mogsdad 2015-08-26 03:32:31

This appears to be a comment on Chris's answer, not an answer to the original question.

@Chris Wagner 2015-06-15 06:39:40

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

@iliketopgun 2015-04-09 14:43:47

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
}

@Jean Le Moignan 2014-06-04 18:49:41

Here's something possibly a little shorter:

sorted(a) {_, _ in arc4random() % 2 == 0}

@Snowman 2014-08-09 15:56:30

Can you explain how this works?

@Jean Le Moignan 2014-08-09 19:56:14

@moby The sort function needs a closure to order elements. This closure takes two parameters (elem1, elem2) and must return true if the first value should appear before the second value, and false otherwise. If we return a random boolean instead... then we just mix up the whole thing :)

@Jean Le Moignan 2014-08-09 19:57:16

@moby Last note: if you don't care about the param names (our case here), one can replace the name with a _.

@Jean Le Moignan 2014-08-09 20:05:16

A new answer to deal with the "sort/sorted" changes in beta5: ` sorted(a) {_, _ in arc4random() % 2 == 0}`

@franklsf95 2014-08-25 22:06:03

Is this mathematically equivalent to shuffling the array (processing each element exactly one time)?

@Jean Le Moignan 2014-08-26 01:21:10

@frankls95 good question. If one thinks about it, though, one will find that good shuffling cannot be done in a o(n) fashion. In fact, what is shuffling if not sorting... backward in time? Therefore, I believe that shuffling must be done in o(n log n) just like quicksort... which the sort function must probably use.

@Jean Le Moignan 2014-08-26 01:22:05

Any mathematician here to confirm or disprove?

@Rob 2014-10-20 05:36:33

As pjs pointed out in response to another very similar answer, this will not generate uniform distribution of results. Use Fisher-Yates Shuffle as shown in Nate Cook's answer.

@Alexander 2016-08-08 20:48:12

This is a clever trick, but is abysmal in terms of quality of the shuffle. For one, this closure should use arc4random_uniform(), becuse it's currently subject to the modulo bias. Secondly,the output depends very strongly on the sorting algorithm (which isn't known to us without looking at the source).

@markiv 2017-10-06 09:15:25

Continuing with this simpler approach, this seems to work quite nicely: collection.sorted { _,_ in arc4random_uniform(1) == 0 }

@cyanide 2018-02-15 02:26:36

I prefer the following arr.sort {, in return arc4random() & 1 == 0 }, as it shuffles in place, without need to reassign

@Daniel Bauke 2014-10-03 11:30:04

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)))])
}

@Rob 2014-10-20 06:21:41

This suffers from, at the very least, a serious off by one error described here whereby a value is always swapped from its original position. This is remedied with let rnd = Int(arc4random_uniform(UInt32(idx + 1))). Also, in FY, you generally iterate from arr.count - 1 down to 1 (or if you iterate from 0 to arr.count - 1, you pick index like Nate shows in accepted answer). See Modern Algorithm section of Fisher-Yates discussion.

@Dan Hixon 2014-06-03 23:48:55

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)

@pjs 2014-06-04 03:54:19

This gives a non-uniform distribution of the results. It also will be O(n log n), where a Fisher-Yates shuffle would give uniformly distributed results in O(n) time.

@Kametrixom 2015-05-30 21:08:45

Also drand48() gives the same pseudo random numbers everytime, unless you set a seed with like srand48(Int(arc4random()))

Related Questions

Sponsored Content

39 Answered Questions

[SOLVED] Loop through an array in JavaScript

79 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5661599 View
  • 7034 Score
  • 79 Answer
  • Tags:   javascript arrays

71 Answered Questions

[SOLVED] How to merge two arrays in JavaScript and de-duplicate items

47 Answered Questions

[SOLVED] How to randomize (shuffle) a JavaScript array?

33 Answered Questions

[SOLVED] For-each over an array in JavaScript?

12 Answered Questions

[SOLVED] How can I add new array elements at the beginning of an array in Javascript?

  • 2011-11-10 00:35:22
  • Moon
  • 667420 View
  • 1347 Score
  • 12 Answer
  • Tags:   javascript arrays

46 Answered Questions

31 Answered Questions

[SOLVED] Create ArrayList from array

18 Answered Questions

[SOLVED] How do I empty an array in JavaScript?

  • 2009-08-05 09:08:39
  • akano1
  • 2186719 View
  • 2199 Score
  • 18 Answer
  • Tags:   javascript arrays

30 Answered Questions

[SOLVED] How to append something to an array?

Sponsored Content