count
zwraca IndexDistance
który typ opisujący podaną odległość między dwoma wskaźnikami kolekcji. IndexDistance
jest wymagane, aby być SignedInteger
, ale nie musi być Int
i może różnić się od Index
. Dlatego nie można utworzyć w zakresie 0..<count - 1
.
Rozwiązaniem jest użycie startIndex
i endIndex
zamiast 0
i 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])
}
}
}
}
Kolejną zaletą jest to, że także działa prawidłowo tablicy plastry (gdzie wskaźnik na pierwszy element jest koniecznie zero).
Należy zauważyć, że zgodnie z nowym "Swift API Design Guidelines", shuffle()
jest "właściwe" nazwa metody Mutating shuffle, i shuffled()
o braku mutacji odpowiednik która zwraca tablicę:
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 (jeszcze bardziej ogólna) Wersja Swift 3 została dodana w międzyczasie do How do I shuffle an array in Swift?.
Na Swift Xcode 4 (9) trzeba wymienić wywołanie funkcji swap()
przez wywołanie metody zbierania swapAt()
. także ograniczenie typu Index
nie jest już potrzebne:
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)
}
}
}
Zobacz SE-0173 Add MutableCollection.swapAt(_:_:)
więcej informacji o swapAt
.
https: // stackoverflow.com/a/27261991/2303865 –
Możliwy duplikat [Jak mogę przetasować tablicę w Swift?] (https://stackoverflow.com/questions/24026510/how-do-i-shuffle-an-array-in-swift) –
Pytanie jest przestarzałe, ponieważ odniesienie zostało zaktualizowane dla Swift 3. –