count
возвращает IndexDistance
, который является тип описания на расстоянии между двумя индексами коллекции. IndexDistance
- должен быть SignedInteger
, но не обязательно должен быть Int
и может быть отличным от Index
. Поэтому невозможно создать диапазон 0..<count - 1
.
Решение состоит в том, чтобы использовать startIndex
и endIndex
вместо 0
и count
:
extension MutableCollection where Index == Int {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
// empty and single-element collections don't shuffle
if count < 2 { return }
for i in startIndex ..< endIndex - 1 {
let j = Int(arc4random_uniform(UInt32(endIndex - i))) + i
if i != j {
swap(&self[i], &self[j])
}
}
}
}
Другим преимуществом является то, что это также корректно работает с массивами ломтиками (где индекс первого элемента не обязательно нуль).
Обратите внимание, что в соответствии с новым "Swift API Design Guidelines", shuffle()
является "правильным" именем метода Mutating в случайном порядке, и shuffled()
для не-мутагенной коллеги, который возвращает массив:
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffled() -> [Iterator.Element] {
var list = Array(self)
list.shuffle()
return list
}
}
Update: A (еще более общий) версия Swift 3 была добавлена к How do I shuffle an array in Swift? тем временем.
Для Swift 4 (Xcode 9) один должен заменить вызов функции swap()
посредством вызова метода в swapAt()
коллекции. не также ограничение на Index
типа больше не нужно:
extension MutableCollection {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
// empty and single-element collections don't shuffle
if count < 2 { return }
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)
}
}
}
См SE-0173 Add MutableCollection.swapAt(_:_:)
для получения дополнительной информации о swapAt
.
https: // StackOverflow.com/a/27261991/2303865 –
Возможный дубликат [Как перетасовать массив в Swift?] (https://stackoverflow.com/questions/24026510/how-do-i-shuffle-an-array-in-swift) –
Вопрос устарел, поскольку ссылка была обновлена для Swift 3. –