Skip to content

Instantly share code, notes, and snippets.

@natecook1000
Last active April 5, 2017 21:17
Show Gist options
  • Save natecook1000/ef096622dab1981823c5 to your computer and use it in GitHub Desktop.
Save natecook1000/ef096622dab1981823c5 to your computer and use it in GitHub Desktop.
Swift 2.0 shuffle / shuffleInPlace
// (c) 2015 Nate Cook, licensed under the MIT license
//
// Fisher-Yates shuffle as protocol extensions
extension CollectionType {
/// Return a copy of `self` with its elements shuffled
func shuffle() -> [Generator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
}
}
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 0..<count - 1 {
let j = Int(arc4random_uniform(UInt32(count - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}
[1, 2, 3].shuffle()
// [2, 3, 1]
let fiveStrings = stride(from: 0, through: 100, by: 5).map(String.init).shuffle()
// ["20", "45", "70", "30", ...]
var numbers = [1, 2, 3, 4]
numbers.shuffleInPlace()
// [3, 2, 1, 4]
@onmyway133
Copy link

Thanks, I see that we can use tuple shuffle, too http://www.fantageek.com/blog/2015/11/27/tuple-shuffle-in-swift/

@Bersaelor
Copy link

if (count -1) > 2147483647 then line 21 will crash on 32Bit devices.

@SilesOcho4
Copy link

Hello natecook1000,

First of all thank you for sharing this shuffle in place extension it was just what I was look for to apply on an app I'm working on. It works wonderfully, thanks.

However, I just updated my project to swift 3 and changes the script to the following:

extension MutableCollection where Index == Int {
mutating func shuffleInPlace() {
if count < 2 { return}
for i in 0..< count - 1 {
let j = Int(arc4random_uniform(UInt32(count - i))) + i
guard i != j else {continue}
swap(&self[i], &self[j])
}
}
}

Only difference is that Instead of "MutableCollectionType" its "MutableCollection", and it then marks an error on the extension. It says: On the.. for i in 0..< count - 1 (Line) : Bainary operator '..>' cannot be applied to operands of type 'Int' or 'self.IndexDistance'.

Please can you fix the extension to work on swift 3. Or tell me how to fix it.

@carterm
Copy link

carterm commented Sep 15, 2016

This just got nerfed in Swift 3.0. "count" is no longer available.

https://stackoverflow.com/questions/37843647/shuffle-array-swift-3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment