¿Cómo aleatorizo o barajo los elementos dentro de una matriz en Swift? Por ejemplo, si mi matriz consta de 52 cartas, quiero barajar la matriz para barajar la baraja.
Esto no es específico de ningún idioma. Simplemente aplique cualquier algoritmo de barajado ...
Gabriele Petronella
8
@ Mitrandir Eso no es cierto. En Ruby uno iría por array.shuffle. No hay necesidad de implementar su propia versión. Supongo que OP estaba buscando algo similar.
Linus Oleander
1
Tenga cuidado, sin embargo, no use cualquier algoritmo de barajado para barajar un mazo de cartas.
njzk2
Respuestas:
627
Esta respuesta detalla cómo barajar con un algoritmo rápido y uniforme (Fisher-Yates) en Swift 4.2+ y cómo agregar la misma función en las diversas versiones anteriores de Swift. Los nombres y el comportamiento de cada versión de Swift coinciden con los métodos de clasificación mutantes y no mutantes para esa versión.
Swift 4.2+
shuffley shuffledson nativos a partir de Swift 4.2. Ejemplo de uso:
let x =[1,2,3].shuffled()// x == [2, 3, 1]
let fiveStrings = stride(from:0, through:100, by:5).map(String.init).shuffled()// fiveStrings == ["20", "45", "70", "30", ...]
var numbers =[1,2,3,4]
numbers.shuffle()// numbers ==[3,2,1,4]
Swift 4.0 y 4.1
Estas extensiones agregan un shuffle()método a cualquier colección mutable (matrices y buffers mutables inseguros) y un shuffled()método a cualquier secuencia:
extensionMutableCollection{/// Shuffles the contents of this collection.
mutatingfunc shuffle(){let c = count
guard c >1else{return}for(firstUnshuffled, unshuffledCount)in zip(indices, stride(from: c, to:1, by:-1)){// Change `Int` in the next line to `IndexDistance` in < Swift 4.1
let d:Int= numericCast(arc4random_uniform(numericCast(unshuffledCount)))let i = index(firstUnshuffled, offsetBy: d)
swapAt(firstUnshuffled, i)}}}extensionSequence{/// Returns an array with the contents of this sequence, shuffled.
func shuffled()->[Element]{var result =Array(self)
result.shuffle()return result
}}
El mismo uso que en los ejemplos de Swift 4.2 anteriores.
Swift 3
Estas extensiones agregan un shuffle()método a cualquier colección mutable y un shuffled()método a cualquier secuencia:
extensionMutableCollectionwhereIndices.Iterator.Element==Index{/// Shuffles the contents of this collection.
mutatingfunc shuffle(){let c = count
guard c >1else{return}for(firstUnshuffled , unshuffledCount)in zip(indices, stride(from: c, to:1, by:-1)){// Change `Int` in the next line to `IndexDistance` in < Swift 3.2
let d:Int= numericCast(arc4random_uniform(numericCast(unshuffledCount)))guard d !=0else{continue}let i = index(firstUnshuffled, offsetBy: d)self.swapAt(firstUnshuffled, i)}}}extensionSequence{/// Returns an array with the contents of this sequence, shuffled.
func shuffled()->[Iterator.Element]{var result =Array(self)
result.shuffle()return result
}}
El mismo uso que en los ejemplos de Swift 4.2 anteriores.
Swift 2
(lenguaje obsoleto: no puede usar Swift 2.x para publicar en iTunes Connect a partir de julio de 2018)
extensionMutableCollectionTypewhereIndex==Int{/// Shuffle the elements of `self` in-place.
mutatingfunc shuffleInPlace(){// empty and single-element collections don't shuffle
if count <2{return}for i in startIndex ..< endIndex -1{let j =Int(arc4random_uniform(UInt32(count - i)))+ i
guard i != j else{continue}
swap(&self[i],&self[j])}}}extensionCollectionType{/// Return a copy of `self` with its elements shuffled.
func shuffle()->[Generator.Element]{var list =Array(self)
list.shuffleInPlace()return list
}}
Uso:
[1,2,3].shuffle()// [2, 3, 1]
let fiveStrings =0.stride(through:100, by:5).map(String.init).shuffle()// ["20", "45", "70", "30", ...]
var numbers =[1,2,3,4]
numbers.shuffleInPlace()//[3,2,1,4]
Swift 1.2
(lenguaje obsoleto: no puede usar Swift 1.x para publicar en iTunes Connect a partir de julio de 2018)
shuffle como un método de matriz mutante
Esta extensión le permitirá barajar una Arrayinstancia mutable en su lugar:
extensionArray{mutatingfunc shuffle(){if count <2{return}for i in0..<(count -1){let j =Int(arc4random_uniform(UInt32(count - i)))+ i
swap(&self[i],&self[j])}}}var numbers =[1,2,3,4,5,6,7,8]
numbers.shuffle()// e.g., numbers ==[6,1,8,3,2,4,7,5]
shuffled como un método de matriz no mutante
Esta extensión le permitirá recuperar una copia barajada de una Arrayinstancia:
extensionArray{func shuffled()->[T]{if count <2{returnself}var list =selffor i in0..<(list.count -1){let j =Int(arc4random_uniform(UInt32(list.count - i)))+ i
swap(&list[i],&list[j])}return list
}}let numbers =[1,2,3,4,5,6,7,8]let mixedup = numbers.shuffled()// e.g., mixedup ==[6,1,8,3,2,4,7,5]
En caso de que desee la versión de la función en Swift 1.2, necesita un poco de actualización a medida countElementsque desaparece, y su reemplazo count, ahora devuelve un, T.Index.Distancepor lo que la restricción debe estar activada C.Index.Distance == Int. Esta versión debería funcionar: gist.github.com/airspeedswift/03d07a9dc86fabdc370f
Airspeed Velocity
2
Esos son los resultados reales: Fisher-Yates debería devolver una permutación aleatoria imparcial de la fuente, por lo que no es necesario que se mueva un elemento en particular. No es una garantía de que no hay elemento se mueve más de una vez, pero a veces el "movimiento" es el mismo índice. El caso más simple es pensar: ¿ [1, 2].shuffled()debería volver eso [2, 1]siempre?
Nate Cook
1
Agregué if count > 0en la parte superior de la función de matriz mutante, para evitar recibir un "error fatal: no se puede formar Range con end <start" cuando se pasa una matriz vacía.
Carl Smith
3
@ Jan: Sí, agregue guard i != j else { continue }antes del intercambio. Archivé un radar, pero el nuevo comportamiento es intencional.
Nate Cook
3
En realidad, shuffleInPlacepuede bloquearse si los índices de recopilación no comienzan en cero, por ejemplo, para un segmento de matriz. for i in 0..<count - 1 debería ser for i in startIndex ..< endIndex - 1(y luego la conversión a Swift 3 se vuelve casi trivial).
Martin R
131
Editar: Como se señaló en otras respuestas, Swift 4.2 finalmente agrega la generación de números aleatorios a la biblioteca estándar, completa con la combinación aleatoria de matrices.
Sin embargo, el GKRandom/ GKRandomDistributionsuite en GameplayKit todavía puede ser útil con el nuevoRandomNumberGenerator protocolo: si agrega extensiones a los RNG de GameplayKit para cumplir con el nuevo protocolo de biblioteca estándar, puede obtener fácilmente:
RNG enviables (que pueden reproducir una secuencia "aleatoria" cuando sea necesario para la prueba)
RNG que sacrifican la robustez por la velocidad
RNG que producen distribuciones no uniformes
... y aún utilizo las nuevas API aleatorias "nativas" en Swift.
El resto de esta respuesta se refiere a tales RNG y / o su uso en compiladores Swift más antiguos.
Ya hay algunas buenas respuestas aquí, así como algunas buenas ilustraciones de por qué escribir su propio shuffle puede ser propenso a errores si no tiene cuidado.
let shuffled =GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
Si desea poder replicar un shuffle o una serie de shuffles, elija y siembre una fuente aleatoria específica; p.ej
let lcg =GKLinearCongruentialRandomSource(seed: mySeedValue)let shuffled = lcg.arrayByShufflingObjects(in: array)
En iOS 10 / macOS 10.12 / tvOS 10, también hay una sintaxis conveniente para barajar a través de una extensión activada NSArray. Por supuesto, eso es un poco engorroso cuando usas un Swift Array(y pierde su tipo de elemento al volver a Swift):
let shuffled1=(array asNSArray).shuffled(using: random)// -> [Any]
let shuffled2=(array asNSArray).shuffled()// use default random source
Pero es bastante fácil hacer un envoltorio Swift que conserve el tipo:
@moby La sortfunción necesita un cierre para ordenar elementos. Este cierre toma dos parámetros (elem1, elem2) y debe devolver verdadero si el primer valor debe aparecer antes del segundo valor, y falso de lo contrario. Si devolvemos un booleano aleatorio en su lugar ... entonces simplemente mezclamos todo :)
Jean Le Moignan
2
¿Algún matemático aquí para confirmar o refutar?
Jean Le Moignan
99
Como pjs señaló en respuesta a otra respuesta muy similar, esto no generará una distribución uniforme de los resultados. Use Fisher-Yates Shuffle como se muestra en la respuesta de Nate Cook.
Rob
1
Este es un truco inteligente, pero es abismal en términos de calidad de la barajadura. Por un lado, este cierre debería usarse arc4random_uniform(), porque actualmente está sujeto al sesgo del módulo. En segundo lugar, la salida depende en gran medida del algoritmo de clasificación (que no conocemos sin mirar la fuente).
Alexander - Restablece a Mónica el
1
Continuando con este enfoque más simple, parece funcionar bastante bien: collection.sorted { _,_ in arc4random_uniform(1) == 0 }
markiv
7
Tomando el algoritmo de Nate, quería ver cómo se vería esto con Swift 2 y las extensiones de protocolo.
Esto es lo que se me ocurrió.
extensionMutableCollectionTypewhereSelf.Index==Int{mutatingfunc shuffleInPlace(){let c =self.count
for i in0..<(c -1){let j =Int(arc4random_uniform(UInt32(c - i)))+ i
swap(&self[i],&self[j])}}}extensionMutableCollectionTypewhereSelf.Index==Int{func shuffle()->Self{var r =selflet c =self.count
for i in0..<(c -1){let j =Int(arc4random_uniform(UInt32(c - i)))+ i
swap(&r[i],&r[j])}return r
}}
Ahora cualquier MutableCollectionType puede usar estos métodos dado que los usa IntcomoIndex
extensionMutableCollection{/// Shuffle the elements of `self` in-place.
mutatingfunc 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)}}}extensionCollection{/// Return a copy of `self` with its elements shuffled
func shuffled()->[Element]{var list =Array(self)
list.shuffle()return list
}}
Los cambios son:
La restricción Indices.Iterator.Element == Indexahora es parte de laCollection protocolo y ya no es necesario imponerla a la extensión.
Swift 4
Mezcla los elementos de una matriz en un bucle for donde i es la relación de mezcla
var cards =[Int]()//Some Array
let i =4// is the mixing ratio
func shuffleCards(){for_in0..< cards.count * i {let card = cards.remove(at:Int(arc4random_uniform(UInt32(cards.count))))
cards.insert(card, at:Int(arc4random_uniform(UInt32(cards.count))))}}
O con extensión Int
func shuffleCards(){for_in0..< cards.count * i {let card = cards.remove(at: cards.count.arc4random)
cards.insert(card, at: cards.count.arc4random)}}extensionInt{var arc4random:Int{ifself>0{
print("Arc for random positiv self \(Int(arc4random_uniform(UInt32(self))))")returnInt(arc4random_uniform(UInt32(self)))}elseifself<0{
print("Arc for random negotiv self \(-Int(arc4random_uniform(UInt32(abs(self)))))")return-Int(arc4random_uniform(UInt32(abs(self))))}else{
print("Arc for random equal 0")return0}}}
Solución Swift 3, siguiendo la respuesta de @Nate Cook: (funciona si el índice comienza con 0, vea los comentarios a continuación)
extensionCollection{/// Return a copy of `self` with its elements shuffled
func shuffle()->[Generator.Element]{var list =Array(self)
list.shuffleInPlace()return list
}}extensionMutableCollectionwhereIndex==Int{/// Shuffle the elements of `self` in-place.
mutatingfunc shuffleInPlace(){// empty and single-element collections don't shuffle
if count <2{return}let countInt = count as!Intfor i in0..<countInt -1{let j =Int(arc4random_uniform(UInt32(countInt - i)))+ i
guard i != j else{continue}
swap(&self[i],&self[j])}}}
Esto puede bloquearse si los índices de recopilación comienzan en 0, por ejemplo, para un segmento de matriz. Intenta correr var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace()varias veces. - Consulte stackoverflow.com/a/37843901/1187415 para obtener una solución correcta.
Martin R
2
Así es como se hace de la manera más simple. import Gamplaykita su VC y use el siguiente código. Probado en Xcode 8.
Con Swift 3, si desea mezclar una matriz en su lugar u obtener una nueva matriz aleatoria de una matriz, AnyIteratorpuede ayudarlo. La idea es crear una matriz de índices a partir de su matriz, mezclar esos índices con una AnyIteratorinstancia y swap(_:_:)función y asignar cada elemento de esta AnyIteratorinstancia con el elemento correspondiente de la matriz.
El siguiente código de Playground muestra cómo funciona:
importDarwin// required for arc4random_uniform
let array =["Jock","Ellie","Sue Ellen","Bobby","JR","Pamela"]var indexArray =Array(array.indices)var index = indexArray.endIndex
let indexIterator:AnyIterator<Int>=AnyIterator{guardlet nextIndex = indexArray.index(index, offsetBy:-1, limitedBy: indexArray.startIndex)else{returnnil}
index = nextIndex
let randomIndex =Int(arc4random_uniform(UInt32(index)))if randomIndex != index {
swap(&indexArray[randomIndex],&indexArray[index])}return indexArray[index]}let newArray = indexIterator.map { array[$0]}
print(newArray)// may print:["Jock","Ellie","Sue Ellen","JR","Pamela","Bobby"]
Puede refactorizar el código anterior y crear una shuffled()función dentro de una Arrayextensión para obtener una nueva matriz aleatoria de una matriz:
importDarwin// required for arc4random_uniform
extensionArray{func shuffled()->Array<Element>{var indexArray =Array<Int>(indices)var index = indexArray.endIndex
let indexIterator =AnyIterator<Int>{guardlet nextIndex = indexArray.index(index, offsetBy:-1, limitedBy: indexArray.startIndex)else{returnnil}
index = nextIndex
let randomIndex =Int(arc4random_uniform(UInt32(index)))if randomIndex != index {
swap(&indexArray[randomIndex],&indexArray[index])}return indexArray[index]}return indexIterator.map {self[$0]}}}
Uso:
let array =["Jock","Ellie","Sue Ellen","Bobby","JR","Pamela"]let newArray = array.shuffled()
print(newArray)// may print:["Bobby","Pamela","Jock","Ellie","JR","Sue Ellen"]
let emptyArray =[String]()let newEmptyArray = emptyArray.shuffled()
print(newEmptyArray)// prints:[]
Como alternativa al código anterior, puede crear una shuffle()función dentro de una Arrayextensión para barajar una matriz en su lugar:
importDarwin// required for arc4random_uniform
extensionArray{mutatingfunc shuffle(){var indexArray =Array<Int>(indices)var index = indexArray.endIndex
let indexIterator =AnyIterator<Int>{guardlet nextIndex = indexArray.index(index, offsetBy:-1, limitedBy: indexArray.startIndex)else{returnnil}
index = nextIndex
let randomIndex =Int(arc4random_uniform(UInt32(index)))if randomIndex != index {
swap(&indexArray[randomIndex],&indexArray[index])}return indexArray[index]}self= indexIterator.map {self[$0]}}}
Uso:
var mutatingArray =["Jock","Ellie","Sue Ellen","Bobby","JR","Pamela"]
mutatingArray.shuffle()
print(mutatingArray)// may print ["Sue Ellen","Pamela","Jock","Ellie","Bobby","JR"]
Esto sufre, como mínimo, un error grave por un error descrito aquí por el cual un valor siempre se intercambia desde su posición original. Esto se remedia con let rnd = Int(arc4random_uniform(UInt32(idx + 1))). Además, en el año fiscal, generalmente itera de arr.count - 1abajo a 1(o si itera de 0a arr.count - 1, elige el índice como muestra Nate en la respuesta aceptada). Vea la sección Algoritmo moderno de la discusión de Fisher-Yates.
Rob
1
¡¡trabajos!!. organismos es la matriz para barajar.
extensionArray{/** Randomizes the order of an array's elements. */mutatingfunc shuffle(){for_in0..<10{
sort {(_,_)in arc4random()< arc4random()}}}}var organisms =["ant","bacteria","cougar","dog","elephant","firefly","goat","hedgehog","iguana"]
print("Original: \(organisms)")
organisms.shuffle()
print("Shuffled: \(organisms)")
En Swift 4.2 , ahora hay un método para ambos, mutableshuffle e inmutableshuffled . Puede leer más sobre la generación aleatoria y el material de matriz aquí .
extensionArray{mutatingfunc shuffled(){for_inself{// generate random indexes that will be swapped
var(a, b)=(Int(arc4random_uniform(UInt32(self.count -1))),Int(arc4random_uniform(UInt32(self.count -1))))if a == b {// if the same indexes are generated swap the first and last
a =0
b =self.count -1}
swap(&self[a],&self[b])}}}var array =[1,2,3,4,5,6,7,8,9,10]
array.shuffled()
print(array)//[9,8,3,5,7,6,4,2,1,10]
Extensión de matriz de trabajo (mutante y no mutante)
Swift 4.1 / Xcode 9
La respuesta principal está en desuso, por lo que me encargué de crear mi propia extensión para mezclar una matriz en la versión más nueva de Swift, Swift 4.1 (Xcode 9):
let array =[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
print(array.shuffled)
Esto se imprime arrayen un orden aleatorio.
Llamada de mutación aleatoria [Array] = [Array]:
var array =[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
array.shuffle()// The array has now been mutated and contains all of its initial
// values, but in a randomized shuffled order
print(array)
Esto se imprime arrayen su orden actual, que ya se ha barajado aleatoriamente.
Espero que esto funcione para todos, si tiene alguna pregunta, sugerencia o comentario, ¡no dude en preguntar!
Esto proporciona una distribución no uniforme de los resultados. También será O (n log n), donde un shuffle de Fisher-Yates daría resultados distribuidos uniformemente en el tiempo O (n).
pjs
También drand48()da los mismos números pseudoaleatorios cada vez, a menos que establezca una semilla con me gustasrand48(Int(arc4random()))
Kametrixom
-3
Se detiene en "swap (& self [i], & self [j])" cuando actualizo la versión de xCode a 7.4 beta.
error fatal: no se admite el intercambio de una ubicación consigo mismo
Encontré la razón por la que i = j (la función de intercambio explotará)
array.shuffle
. No hay necesidad de implementar su propia versión. Supongo que OP estaba buscando algo similar.Respuestas:
Esta respuesta detalla cómo barajar con un algoritmo rápido y uniforme (Fisher-Yates) en Swift 4.2+ y cómo agregar la misma función en las diversas versiones anteriores de Swift. Los nombres y el comportamiento de cada versión de Swift coinciden con los métodos de clasificación mutantes y no mutantes para esa versión.
Swift 4.2+
shuffle
yshuffled
son nativos a partir de Swift 4.2. Ejemplo de uso:Swift 4.0 y 4.1
Estas extensiones agregan un
shuffle()
método a cualquier colección mutable (matrices y buffers mutables inseguros) y unshuffled()
método a cualquier secuencia:El mismo uso que en los ejemplos de Swift 4.2 anteriores.
Swift 3
Estas extensiones agregan un
shuffle()
método a cualquier colección mutable y unshuffled()
método a cualquier secuencia:El mismo uso que en los ejemplos de Swift 4.2 anteriores.
Swift 2
(lenguaje obsoleto: no puede usar Swift 2.x para publicar en iTunes Connect a partir de julio de 2018)
Uso:
Swift 1.2
(lenguaje obsoleto: no puede usar Swift 1.x para publicar en iTunes Connect a partir de julio de 2018)
shuffle
como un método de matriz mutanteEsta extensión le permitirá barajar una
Array
instancia mutable en su lugar:shuffled
como un método de matriz no mutanteEsta extensión le permitirá recuperar una copia barajada de una
Array
instancia:fuente
countElements
que desaparece, y su reemplazocount
, ahora devuelve un,T.Index.Distance
por lo que la restricción debe estar activadaC.Index.Distance == Int
. Esta versión debería funcionar: gist.github.com/airspeedswift/03d07a9dc86fabdc370f[1, 2].shuffled()
debería volver eso[2, 1]
siempre?if count > 0
en la parte superior de la función de matriz mutante, para evitar recibir un "error fatal: no se puede formar Range con end <start" cuando se pasa una matriz vacía.guard i != j else { continue }
antes del intercambio. Archivé un radar, pero el nuevo comportamiento es intencional.shuffleInPlace
puede bloquearse si los índices de recopilación no comienzan en cero, por ejemplo, para un segmento de matriz.for i in 0..<count - 1
debería serfor i in startIndex ..< endIndex - 1
(y luego la conversión a Swift 3 se vuelve casi trivial).Editar: Como se señaló en otras respuestas, Swift 4.2 finalmente agrega la generación de números aleatorios a la biblioteca estándar, completa con la combinación aleatoria de matrices.
Sin embargo, el
GKRandom
/GKRandomDistribution
suite en GameplayKit todavía puede ser útil con el nuevoRandomNumberGenerator
protocolo: si agrega extensiones a los RNG de GameplayKit para cumplir con el nuevo protocolo de biblioteca estándar, puede obtener fácilmente:... y aún utilizo las nuevas API aleatorias "nativas" en Swift.
El resto de esta respuesta se refiere a tales RNG y / o su uso en compiladores Swift más antiguos.
Ya hay algunas buenas respuestas aquí, así como algunas buenas ilustraciones de por qué escribir su propio shuffle puede ser propenso a errores si no tiene cuidado.
En iOS 9, macOS 10.11 y tvOS 9 (o posterior), no tiene que escribir el suyo. Hay una implementación eficiente y correcta de Fisher-Yates en GameplayKit (que, a pesar del nombre, no es solo para juegos).
Si solo quieres un shuffle único:
Si desea poder replicar un shuffle o una serie de shuffles, elija y siembre una fuente aleatoria específica; p.ej
En iOS 10 / macOS 10.12 / tvOS 10, también hay una sintaxis conveniente para barajar a través de una extensión activada
NSArray
. Por supuesto, eso es un poco engorroso cuando usas un SwiftArray
(y pierde su tipo de elemento al volver a Swift):Pero es bastante fácil hacer un envoltorio Swift que conserve el tipo:
fuente
let shuffled = lcg.arrayByShufflingObjects(in: array)
¡En Swift 2.0 , GameplayKit puede venir al rescate! (compatible con iOS9 o posterior)
fuente
import GameplayKit.GKRandomSource
Aquí hay algo posiblemente un poco más corto:
fuente
sort
función necesita un cierre para ordenar elementos. Este cierre toma dos parámetros (elem1, elem2) y debe devolver verdadero si el primer valor debe aparecer antes del segundo valor, y falso de lo contrario. Si devolvemos un booleano aleatorio en su lugar ... entonces simplemente mezclamos todo :)arc4random_uniform()
, porque actualmente está sujeto al sesgo del módulo. En segundo lugar, la salida depende en gran medida del algoritmo de clasificación (que no conocemos sin mirar la fuente).collection.sorted { _,_ in arc4random_uniform(1) == 0 }
Tomando el algoritmo de Nate, quería ver cómo se vería esto con Swift 2 y las extensiones de protocolo.
Esto es lo que se me ocurrió.
Ahora cualquier
MutableCollectionType
puede usar estos métodos dado que los usaInt
comoIndex
fuente
En mi caso, tuve algunos problemas para intercambiar objetos en Array. Luego me rasqué la cabeza y fui a reinventar la rueda.
fuente
Esta es una versión de la implementación de Nate del shuffle Fisher-Yates para Swift 4 (Xcode 9).
Los cambios son:
Indices.Iterator.Element == Index
ahora es parte de laCollection
protocolo y ya no es necesario imponerla a la extensión.swapAt()
a la colección, compare SE-0173 AgregarMutableCollection.swapAt(_:_:)
.Element
es un alias paraIterator.Element
.fuente
Esto es lo que uso:
fuente
Swift 4 Mezcla los elementos de una matriz en un bucle for donde i es la relación de mezcla
O con extensión Int
fuente
Solución Swift 3, siguiendo la respuesta de @Nate Cook: (funciona si el índice comienza con 0, vea los comentarios a continuación)
fuente
var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace()
varias veces. - Consulte stackoverflow.com/a/37843901/1187415 para obtener una solución correcta.Así es como se hace de la manera más simple.
import Gamplaykit
a su VC y use el siguiente código. Probado en Xcode 8.Si desea obtener una cadena aleatoria de una matriz, puede usar el siguiente código.
fuente
Con Swift 3, si desea mezclar una matriz en su lugar u obtener una nueva matriz aleatoria de una matriz,
AnyIterator
puede ayudarlo. La idea es crear una matriz de índices a partir de su matriz, mezclar esos índices con unaAnyIterator
instancia yswap(_:_:)
función y asignar cada elemento de estaAnyIterator
instancia con el elemento correspondiente de la matriz.El siguiente código de Playground muestra cómo funciona:
Puede refactorizar el código anterior y crear una
shuffled()
función dentro de unaArray
extensión para obtener una nueva matriz aleatoria de una matriz:Uso:
Como alternativa al código anterior, puede crear una
shuffle()
función dentro de unaArray
extensión para barajar una matriz en su lugar:Uso:
fuente
También puede usar la
swap
función genérica e implementar el mencionado Fisher-Yates:o menos detallado:
fuente
let rnd = Int(arc4random_uniform(UInt32(idx + 1)))
. Además, en el año fiscal, generalmente itera dearr.count - 1
abajo a1
(o si itera de0
aarr.count - 1
, elige el índice como muestra Nate en la respuesta aceptada). Vea la sección Algoritmo moderno de la discusión de Fisher-Yates.¡¡trabajos!!. organismos es la matriz para barajar.
fuente
En Swift 4.2 , ahora hay un método para ambos, mutable
shuffle
e inmutableshuffled
. Puede leer más sobre la generación aleatoria y el material de matriz aquí .fuente
Así es como mezclar una matriz con una semilla en Swift 3.0.
fuente
fuente
Esto es lo que uso:
fuente
Ejemplo simple:
fuente
Extensión de matriz de trabajo (mutante y no mutante)
Swift 4.1 / Xcode 9
La respuesta principal está en desuso, por lo que me encargué de crear mi propia extensión para mezclar una matriz en la versión más nueva de Swift, Swift 4.1 (Xcode 9):
Llamada aleatoria no mutante
[Array] -> [Array]
:Esto se imprime
array
en un orden aleatorio.Llamada de mutación aleatoria
[Array] = [Array]
:Esto se imprime
array
en su orden actual, que ya se ha barajado aleatoriamente.Espero que esto funcione para todos, si tiene alguna pregunta, sugerencia o comentario, ¡no dude en preguntar!
fuente
En SWIFT 4
fuente
Si desea utilizar la función de bucle Swift For simple, use esto ->
Swift Array sufle usando la extensión ->
fuente
A partir de swift 4.2 hay dos funciones útiles:
y
fuente
Aquí hay un código que se ejecuta en el patio de recreo. No necesitará importar Darwin en un proyecto real de Xcode.
fuente
drand48()
da los mismos números pseudoaleatorios cada vez, a menos que establezca una semilla con me gustasrand48(Int(arc4random()))
Se detiene en "swap (& self [i], & self [j])" cuando actualizo la versión de xCode a 7.4 beta.
error fatal: no se admite el intercambio de una ubicación consigo mismo
Entonces agrego una condición como a continuación
YA! Esta bien para mi.
fuente