Shuffle array swift 3

¿Cómo puedo convertir la función de abajo para swift 3 ? Actualmente, obtener un 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]) } } } 

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

count devuelve un IndexDistance que es el tipo que describe la distancia entre dos índices de colección. IndexDistance debe ser un SignedInteger , pero no necesita ser un Int y puede ser diferente de Index . Por lo tanto, no es posible crear el rango 0.. .

Una solución es usar startIndex y endIndex lugar de 0 y 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]) } } } } 

Otra ventaja es que esto también funciona correctamente con segmentos de matriz (donde el índice del primer elemento no es necesariamente cero).

Tenga en cuenta que de acuerdo con las nuevas "Directrices de diseño de la API Swift" , shuffle() es el nombre "apropiado" para un método mutante de mutación y shuffled() para la contraparte no mutante que devuelve una matriz:

 extension Collection { /// Return a copy of `self` with its elements shuffled func shuffled() -> [Iterator.Element] { var list = Array(self) list.shuffle() return list } } 

Actualización: Una (incluso más general) versión de Swift 3 se ha agregado a ¿Cómo mezclo una matriz en Swift? mientras tanto.


Para Swift 4 (Xcode 9) hay que reemplazar la llamada a la función swap() por una llamada al método swapAt() de la colección. Además, la restricción en el tipo de Index ya no es necesaria:

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

Vea SE-0173 Agregue MutableCollection.swapAt(_:_:) para más información sobre swapAt .


A partir de Swift 4.2 (Xcode 10, actualmente en beta), con la implementación de SE-0202 Random Unification , shuffle() y shuffled() son parte de la biblioteca estándar de Swift.

Hay una mezcla de fisher-yates en Gamekit:

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

También puede pasar y almacenar una semilla aleatoria, por lo que obtiene la misma secuencia de valores aleatorios pseudoaleatorios cada vez que suministra la misma semilla en caso de que necesite recrear una simulación.

 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) 

Sugeriría simplemente reorganizar matrices en lugar de tratar de extender esto a colecciones en general:

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

Puede usar la Extensión NSArray del marco GameplayKit para esto:

 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]