Shuffle array swift 3

Come posso convertire la funzione seguente in swift 3 ? Attualmente Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance' un Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance' .

 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]) } } } 

riferimento: https://stackoverflow.com/a/24029847/5222077

count restituisce IndexDistance che è il tipo che descrive la distanza tra due indici di raccolta. IndexDistance deve essere un SignedInteger , ma non deve necessariamente essere un Int e può essere diverso Index . Pertanto non è ansible creare l’intervallo 0.. .

Una soluzione è usare startIndex e endIndex invece di 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 funziona anche correttamente con le sezioni dell'array (dove l'indice del primo elemento non è necessariamente zero).

Si noti che, secondo le nuove "Linee guida per la progettazione dell'API Swift" , shuffle() è il nome "corretto" per un metodo shuffle mutante e shuffled() per la controparte non mutante 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) è stata aggiunta la versione di Swift 3 a Come mischiare un array in Swift? nel frattempo.


Per Swift 4 (Xcode 9) si deve sostituire la chiamata alla funzione swap() con una chiamata al metodo swapAt() della collezione. Inoltre, la restrizione sul tipo di Index non è più necessaria:

 extension MutableCollection { /// Shuffle the elements of `self` in-place. mutating func shuffle() { 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 Aggiungi MutableCollection.swapAt(_:_:) per maggiori informazioni su swapAt .


A partire da Swift 4.2 (Xcode 10, attualmente in versione beta), con l'implementazione di SE-0202 Random Unification , shuffle() e shuffled() fanno parte della libreria standard di Swift.

C’è un gioco di pesca yates in Gamekit:

 import GameKit let unshuffledArray = [1,2,3,4] let shuffledArray = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: unshuffledArray) print(shuffledArray) 

Puoi anche inoltrare e archiviare un seed casuale, in modo da ottenere la stessa sequenza di valori shuffle pseudocasuali ogni volta che fornisci lo stesso seed nel caso in cui sia necessario ricreare una simulazione.

 import GameKit let unshuffledArray = [1,2,3,4] let randomSource = GKLinearCongruentialRandomSource(seed: 1) let shuffledArray = randomSource.arrayByShufflingObjects(in: unshuffledArray) //Always [1,4,2,3] print(shuffledArray) 

Suggerirei semplicemente di mischiare gli array invece di cercare di estenderli alle raccolte in generale:

 extension Array { mutating func shuffle () { for i in (0.. 

Puoi usare l’estensione NSArray dal framework GameplayKit per questo:

 import GameplayKit extension Collection { func shuffled() -> [Iterator.Element] { let shuffledArray = (self as? NSArray)?.shuffled() let outputArray = shuffledArray as? [Iterator.Element] return outputArray ?? [] } mutating func shuffle() { if let selfShuffled = self.shuffled() as? Self { self = selfShuffled } } } // Usage example: var numbers = [1,2,3,4,5] numbers.shuffle() print(numbers) // output example: [2, 3, 5, 4, 1] print([10, "hi", 9.0].shuffled()) // output example: [hi, 10, 9]