How can I convert the function below to to swift 3
? Currently getting a Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance'
error.
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 }
for i in 0..<count - 1 { //error takes place here
let j = Int(arc4random_uniform(UInt32(count - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}
reference: https://stackoverflow.com/a/24029847/5222077
I would suggest simply shuffling arrays instead of trying to extend this to collections in general:
You can use the NSArray Extension from GameplayKit framework for this:
There is a fisher-yates shuffle in Gamekit:
You can also pass in and store a random seed, so you get the same sequence of pseudorandom shuffle values every time you supply the same seed in case you need to recreate a simulation.
count
returns anIndexDistance
which is the type describing the distance between two collection indices.IndexDistance
is required to be aSignedInteger
, but need not be anInt
and can be different fromIndex
. Therefore it is not possible to create the range0..<count - 1
.A solution is to use
startIndex
andendIndex
instead of0
andcount
:Another advantage is that this also works correctly with array slices (where the index of the first element is not necessarily zero).
Note that according to the new "Swift API Design Guidelines",
shuffle()
is the "proper" name for a mutating shuffle method, andshuffled()
for the non-mutating counterpart which returns an array:Update: A (even more general) Swift 3 version has been added to How do I shuffle an array in Swift? in the meantime.
For Swift 4 (Xcode 9) one has to replace the call to the
swap()
function by a call to theswapAt()
method of the collection. Also the restriction on theIndex
type is no longer needed:See SE-0173 Add
MutableCollection.swapAt(_:_:)
for more information aboutswapAt
.As of Swift 4.2 (Xcode 10, currently in beta), with the implementation of SE-0202 Random Unification,
shuffle()
andshuffled()
are part of the Swift standard library.