count
restituisce un IndexDistance
che è il tipo descrive distanza tra due indici di raccolta. IndexDistance
è richiesto per essere un SignedInteger
, ma non deve essere un Int
e può essere diverso da Index
. Pertanto non è possibile creare nell'intervallo 0..<count - 1
.
Una soluzione è quella di utilizzare startIndex
e endIndex
anziché 0
e 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])
}
}
}
}
Un altro vantaggio è che questo funziona correttamente anche con matrice fette (dove l'indice del primo elemento non è necessariamente zero).
nota che in base al nuovo "Swift API Design Guidelines", shuffle()
è il nome "corretto" per un metodo mutante shuffle, e shuffled()
per il non-mutanti controparte, che restituisce un array:
extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffled() -> [Iterator.Element] {
var list = Array(self)
list.shuffle()
return list
}
}
Aggiornamento: A (ancora più generale) la versione Swift 3 è stata aggiunta a How do I shuffle an array in Swift? nel frattempo.
Per Swift 4 (Xcode 9) si deve sostituire la chiamata alla funzione swap()
da una chiamata al metodo della raccolta swapAt()
. Inoltre non è più necessario la restrizione del tipo 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)
}
}
}
Vedi SE-0173 Add MutableCollection.swapAt(_:_:)
per ulteriori informazioni su swapAt
.
fonte
2016-06-15 19:11:33
https: // StackOverflow.com/a/27261991/2303865 –
Possibile duplicato di [Come mischiare un array in Swift?] (https://stackoverflow.com/questions/24026510/how-do-i-shuffle-an-array-in-swift) –
La domanda è obsoleta, poiché il riferimento è stato aggiornato per Swift 3. –