Como faço para aleatorizar ou embaralhar os elementos em uma matriz no Swift? Por exemplo, se minha matriz consiste em 52 cartas, quero embaralhar a matriz para embaralhar o baralho.
isso não é específico para nenhum idioma. Basta aplicar qualquer algoritmo de embaralhamento ...
Gabriele Petronella
8
@Mithrandir Isso não é verdade. Em Ruby, alguém procuraria array.shuffle. Não há necessidade de implementar sua própria versão. Eu acho que o OP estava procurando por algo semelhante.
Linus Oleander
1
tenha cuidado, no entanto, não use qualquer algoritmo de reprodução aleatória para embaralhar um baralho de cartas.
Njzk2 17/10/19
Respostas:
627
Esta resposta detalha como embaralhar com um algoritmo rápido e uniforme (Fisher-Yates) no Swift 4.2+ e como adicionar o mesmo recurso nas várias versões anteriores do Swift. A nomeação e o comportamento de cada versão do Swift correspondem aos métodos de classificação com e sem mutação para essa versão.
Swift 4.2+
shufflee shuffledsão nativos a partir do Swift 4.2. Exemplo 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 e 4.1
Essas extensões adicionam um shuffle()método a qualquer coleção mutável (matrizes e buffers mutáveis inseguros) e um shuffled()método a qualquer sequência:
extensionMutableCollection{/// Shuffles the contents of this collection.mutatingfunc shuffle(){let c = countguard 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.1let 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}}
O mesmo uso dos exemplos do Swift 4.2 acima.
Swift 3
Essas extensões adicionam um shuffle()método a qualquer coleção mutável e um shuffled()método a qualquer sequência:
extensionMutableCollectionwhereIndices.Iterator.Element==Index{/// Shuffles the contents of this collection.mutatingfunc shuffle(){let c = countguard 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.2let 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}}
O mesmo uso dos exemplos do Swift 4.2 acima.
Swift 2
(idioma obsoleto: você não pode usar o Swift 2.x para publicar no iTunes Connect a partir de julho de 2018)
extensionMutableCollectionTypewhereIndex==Int{/// Shuffle the elements of `self` in-place.mutatingfunc shuffleInPlace(){// empty and single-element collections don't shuffleif count <2{return}for i in startIndex ..< endIndex -1{let j =Int(arc4random_uniform(UInt32(count - i)))+ iguard 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}}
Caso você deseje a versão da função no Swift 1.2, ela precisa de um pouco de atualização à medida que countElementsdesaparece, e sua substituição countagora retorna um T.Index.Distancepara que a restrição precise estar ativa C.Index.Distance == Int. Esta versão deve funcionar: gist.github.com/airspeedswift/03d07a9dc86fabdc370f
Airspeed Velocity
2
Essa é a saída real - Fisher-Yates deve retornar uma permutação aleatória imparcial da fonte, portanto não há exigência de que um elemento específico se mova. Não é uma garantia de que nenhum elemento se move mais de uma vez, mas às vezes o "movimento" é o mesmo índice. O caso mais simples é pensar [1, 2].shuffled()- isso deve retornar [2, 1]sempre?
Nate Cook
1
Eu adicionei if count > 0na parte superior da função de matriz mutante, para evitar o recebimento de um "erro fatal: não é possível formar Range com end <start" quando é passada uma matriz vazia.
Carl Smith
3
@ Jan: Sim, adicione guard i != j else { continue }antes da troca. Arquivei um radar, mas o novo comportamento é intencional.
Nate Cook
3
Na verdade, shuffleInPlacepode travar se os índices de coleta não começarem em zero, por exemplo, para uma fatia da matriz. for i in 0..<count - 1 deve ser for i in startIndex ..< endIndex - 1(e a conversão para o Swift 3 se torna quase trivial).
Martin R
131
Edit: Como observado em outras respostas, o Swift 4.2 finalmente adiciona geração aleatória de números à biblioteca padrão, completa com a reprodução aleatória da matriz.
No entanto, o GKRandom/ GKRandomDistributionsuite no GameplayKit ainda pode ser útil com o novo RandomNumberGeneratorprotocolo - se você adicionar extensões aos RNGs do GameplayKit para estar em conformidade com o novo protocolo de biblioteca padrão, poderá obter facilmente:
RNGs enviados (que podem reproduzir uma sequência "aleatória" quando necessário para teste)
RNGs que sacrificam robustez por velocidade
RNGs que produzem distribuições não uniformes
... e ainda faça uso das novas e agradáveis APIs aleatórias "nativas" no Swift.
O restante desta resposta diz respeito a esses RNGs e / ou seu uso em compiladores Swift mais antigos.
Já existem boas respostas aqui, bem como algumas boas ilustrações de por que escrever seu próprio shuffle pode ser propenso a erros se você não tomar cuidado.
let shuffled =GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
Se você deseja replicar um shuffle ou uma série de shuffles, escolha e propague uma fonte aleatória específica; por exemplo
let lcg =GKLinearCongruentialRandomSource(seed: mySeedValue)let shuffled = lcg.arrayByShufflingObjects(in: array)
No iOS 10 / macOS 10.12 / tvOS 10, também há uma sintaxe de conveniência para embaralhar por meio de uma extensão NSArray. Claro, isso é um pouco complicado quando você usa um Swift Array(e perde o tipo de elemento ao voltar ao Swift):
let shuffled1=(array asNSArray).shuffled(using: random)// -> [Any]let shuffled2=(array asNSArray).shuffled()// use default random source
Mas é muito fácil criar um wrapper Swift que preserva o tipo:
@moby A sortfunção precisa de um fechamento para solicitar elementos. Esse fechamento usa dois parâmetros (elem1, elem2) e deve retornar true se o primeiro valor aparecer antes do segundo valor e false caso contrário. Se voltarmos um booleano aleatória vez ... então nós apenas misturar a coisa toda :)
Jean Le Moignan
2
Algum matemático aqui para confirmar ou refutar?
Jean Le Moignan
9
Como pjs apontou em resposta a outra resposta muito semelhante, isso não gerará distribuição uniforme de resultados. Use Fisher-Yates Shuffle, como mostrado na resposta de Nate Cook.
Rob
1
Este é um truque inteligente, mas é péssimo em termos de qualidade do shuffle. Por um lado, esse fechamento deve ser utilizado arc4random_uniform(), pois atualmente está sujeito ao viés do módulo. Em segundo lugar, a saída depende muito do algoritmo de classificação (que não é conhecido por nós sem observar a fonte).
Alexander - Restabelece Monica
1
Continuando com esta abordagem mais simples, isso parece funcionar muito bem: collection.sorted { _,_ in arc4random_uniform(1) == 0 }
markiv
7
Tomando o algoritmo de Nate, eu queria ver como isso ficaria com o Swift 2 e as extensões de protocolo.
Isto é o que eu vim com.
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
}}
Agora, qualquer um MutableCollectionTypepode usar esses métodos, pois usa Intcomo umIndex
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
}}
As mudanças são:
A restrição Indices.Iterator.Element == Indexagora faz parte do Collectionprotocolo e não precisa mais ser imposta à extensão.
Swift 4
Embaralhe os elementos de uma matriz em um loop for, onde i é a taxa de mixagem
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))))}}
Ou com extensão 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}}}
Solução Swift 3, seguindo a resposta @Nate Cook: (funcione se o índice começar com 0, veja os comentários abaixo)
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])}}}
Isso pode falhar se os índices de coleção começarem em 0, por exemplo, para uma fatia da matriz. Tente executar var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace()várias vezes. - Consulte stackoverflow.com/a/37843901/1187415 para obter uma solução correta.
Martin R
2
É assim que é feito da maneira mais simples. import Gamplaykitao seu VC e use o código abaixo. Testado no Xcode 8.
Com o Swift 3, se você deseja embaralhar uma matriz no local ou obter uma nova matriz embaralhada de uma matriz, AnyIteratorpode ajudá-lo. A idéia é criar uma matriz de índices a partir da matriz, embaralhá-los com uma AnyIteratorinstância e swap(_:_:)função e mapear cada elemento dessa AnyIteratorinstância com o elemento correspondente da matriz.
O seguinte código do Playground mostra como ele 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"]
Você pode refatorar o código anterior e criar uma shuffled()função dentro de uma Arrayextensão para obter uma nova matriz embaralhada de uma 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 ao código anterior, você pode criar uma shuffle()função dentro de uma Arrayextensão para embaralhar uma matriz no 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"]
Isso sofre, no mínimo, com um erro grave descrito aqui, no qual um valor é sempre trocado de sua posição original. Isso é remediado com let rnd = Int(arc4random_uniform(UInt32(idx + 1))). Além disso, no EF, você geralmente itera de arr.count - 1baixo para 1(ou, se você iterar de 0para arr.count - 1, escolhe um índice como o Nate mostra na resposta aceita). Veja a seção Algoritmo Moderno da discussão de Fisher-Yates.
22414 Rob às
1
trabalho!!. organismos é a matriz para embaralhar.
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)")
No Swift 4.2 , agora existe um método para mutávelshuffle e imutávelshuffled . Você pode ler mais sobre as coisas aleatórias de geração e matriz aqui .
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]
Extensão de matriz de trabalho (com e sem mutação)
Swift 4.1 / Xcode 9
A resposta principal foi descontinuada, então decidi criar minha própria extensão para embaralhar uma matriz na versão mais recente do Swift, Swift 4.1 (Xcode 9):
Chamada aleatória sem mutação de chamada [Array] -> [Array]:
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)
Isso é impresso arrayem uma ordem aleatória.
Aleatório de mutação de chamada [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)
Isso é impresso arrayem sua ordem atual, que já foi aleatoriamente embaralhada.
Espero que isso funcione para todos, se você tiver quaisquer perguntas, sugestões ou comentários, não hesite em perguntar!
Isso fornece uma distribuição não uniforme dos resultados. Também será O (n log n), onde um embaralhamento de Fisher-Yates daria resultados uniformemente distribuídos em O (n) tempo.
pjs
Também drand48()dá o mesmo pseudo números aleatórios toda vez que, a menos que você definir uma semente com gostosrand48(Int(arc4random()))
Kametrixom
-3
Ele pára em "swap (& self [i], & self [j])" quando atualizo a versão xCode para 7.4 beta.
erro fatal: a troca de um local consigo mesma não é suportada
Encontrei o motivo pelo qual i = j (a função de troca explodiu)
array.shuffle
. Não há necessidade de implementar sua própria versão. Eu acho que o OP estava procurando por algo semelhante.Respostas:
Esta resposta detalha como embaralhar com um algoritmo rápido e uniforme (Fisher-Yates) no Swift 4.2+ e como adicionar o mesmo recurso nas várias versões anteriores do Swift. A nomeação e o comportamento de cada versão do Swift correspondem aos métodos de classificação com e sem mutação para essa versão.
Swift 4.2+
shuffle
eshuffled
são nativos a partir do Swift 4.2. Exemplo de uso:Swift 4.0 e 4.1
Essas extensões adicionam um
shuffle()
método a qualquer coleção mutável (matrizes e buffers mutáveis inseguros) e umshuffled()
método a qualquer sequência:O mesmo uso dos exemplos do Swift 4.2 acima.
Swift 3
Essas extensões adicionam um
shuffle()
método a qualquer coleção mutável e umshuffled()
método a qualquer sequência:O mesmo uso dos exemplos do Swift 4.2 acima.
Swift 2
(idioma obsoleto: você não pode usar o Swift 2.x para publicar no iTunes Connect a partir de julho de 2018)
Uso:
Swift 1.2
(idioma obsoleto: você não pode usar o Swift 1.x para publicar no iTunes Connect a partir de julho de 2018)
shuffle
como um método de matriz mutanteEsta extensão permitirá embaralhar uma
Array
instância mutável no lugar:shuffled
como um método de matriz não mutanteEsta extensão permitirá recuperar uma cópia aleatória de uma
Array
instância:fonte
countElements
desaparece, e sua substituiçãocount
agora retorna umT.Index.Distance
para que a restrição precise estar ativaC.Index.Distance == Int
. Esta versão deve funcionar: gist.github.com/airspeedswift/03d07a9dc86fabdc370f[1, 2].shuffled()
- isso deve retornar[2, 1]
sempre?if count > 0
na parte superior da função de matriz mutante, para evitar o recebimento de um "erro fatal: não é possível formar Range com end <start" quando é passada uma matriz vazia.guard i != j else { continue }
antes da troca. Arquivei um radar, mas o novo comportamento é intencional.shuffleInPlace
pode travar se os índices de coleta não começarem em zero, por exemplo, para uma fatia da matriz.for i in 0..<count - 1
deve serfor i in startIndex ..< endIndex - 1
(e a conversão para o Swift 3 se torna quase trivial).Edit: Como observado em outras respostas, o Swift 4.2 finalmente adiciona geração aleatória de números à biblioteca padrão, completa com a reprodução aleatória da matriz.
No entanto, o
GKRandom
/GKRandomDistribution
suite no GameplayKit ainda pode ser útil com o novoRandomNumberGenerator
protocolo - se você adicionar extensões aos RNGs do GameplayKit para estar em conformidade com o novo protocolo de biblioteca padrão, poderá obter facilmente:... e ainda faça uso das novas e agradáveis APIs aleatórias "nativas" no Swift.
O restante desta resposta diz respeito a esses RNGs e / ou seu uso em compiladores Swift mais antigos.
Já existem boas respostas aqui, bem como algumas boas ilustrações de por que escrever seu próprio shuffle pode ser propenso a erros se você não tomar cuidado.
No iOS 9, macOS 10.11 e tvOS 9 (ou posterior), você não precisa escrever por conta própria. Há uma implementação eficiente e correta de Fisher-Yates no GameplayKit (que, apesar do nome, não é apenas para jogos).
Se você quer apenas um shuffle exclusivo:
Se você deseja replicar um shuffle ou uma série de shuffles, escolha e propague uma fonte aleatória específica; por exemplo
No iOS 10 / macOS 10.12 / tvOS 10, também há uma sintaxe de conveniência para embaralhar por meio de uma extensão
NSArray
. Claro, isso é um pouco complicado quando você usa um SwiftArray
(e perde o tipo de elemento ao voltar ao Swift):Mas é muito fácil criar um wrapper Swift que preserva o tipo:
fonte
let shuffled = lcg.arrayByShufflingObjects(in: array)
No Swift 2.0 , o GameplayKit pode ajudar! (suportado pelo iOS9 ou posterior)
fonte
import GameplayKit.GKRandomSource
Aqui está algo possivelmente um pouco mais curto:
fonte
sort
função precisa de um fechamento para solicitar elementos. Esse fechamento usa dois parâmetros (elem1, elem2) e deve retornar true se o primeiro valor aparecer antes do segundo valor e false caso contrário. Se voltarmos um booleano aleatória vez ... então nós apenas misturar a coisa toda :)arc4random_uniform()
, pois atualmente está sujeito ao viés do módulo. Em segundo lugar, a saída depende muito do algoritmo de classificação (que não é conhecido por nós sem observar a fonte).collection.sorted { _,_ in arc4random_uniform(1) == 0 }
Tomando o algoritmo de Nate, eu queria ver como isso ficaria com o Swift 2 e as extensões de protocolo.
Isto é o que eu vim com.
Agora, qualquer um
MutableCollectionType
pode usar esses métodos, pois usaInt
como umIndex
fonte
No meu caso, tive alguns problemas ao trocar objetos no Array. Então coçei minha cabeça e fui reinventar a roda.
fonte
Esta é uma versão da implementação de Nate do shuffle Fisher-Yates para Swift 4 (Xcode 9).
As mudanças são:
Indices.Iterator.Element == Index
agora faz parte doCollection
protocolo e não precisa mais ser imposta à extensão.swapAt()
a coleção, compare SE-0173 AddMutableCollection.swapAt(_:_:)
.Element
é um alias paraIterator.Element
.fonte
Isto é o que eu uso:
fonte
Swift 4 Embaralhe os elementos de uma matriz em um loop for, onde i é a taxa de mixagem
Ou com extensão Int
fonte
Solução Swift 3, seguindo a resposta @Nate Cook: (funcione se o índice começar com 0, veja os comentários abaixo)
fonte
var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace()
várias vezes. - Consulte stackoverflow.com/a/37843901/1187415 para obter uma solução correta.É assim que é feito da maneira mais simples.
import Gamplaykit
ao seu VC e use o código abaixo. Testado no Xcode 8.Se você deseja obter uma String embaralhada de uma Matriz, pode usar o código abaixo.
fonte
Com o Swift 3, se você deseja embaralhar uma matriz no local ou obter uma nova matriz embaralhada de uma matriz,
AnyIterator
pode ajudá-lo. A idéia é criar uma matriz de índices a partir da matriz, embaralhá-los com umaAnyIterator
instância eswap(_:_:)
função e mapear cada elemento dessaAnyIterator
instância com o elemento correspondente da matriz.O seguinte código do Playground mostra como ele funciona:
Você pode refatorar o código anterior e criar uma
shuffled()
função dentro de umaArray
extensão para obter uma nova matriz embaralhada de uma matriz:Uso:
Como alternativa ao código anterior, você pode criar uma
shuffle()
função dentro de umaArray
extensão para embaralhar uma matriz no lugar:Uso:
fonte
Você também pode usar a
swap
função genérica e implementar Fisher-Yates mencionados:ou menos detalhado:
fonte
let rnd = Int(arc4random_uniform(UInt32(idx + 1)))
. Além disso, no EF, você geralmente itera dearr.count - 1
baixo para1
(ou, se você iterar de0
paraarr.count - 1
, escolhe um índice como o Nate mostra na resposta aceita). Veja a seção Algoritmo Moderno da discussão de Fisher-Yates.trabalho!!. organismos é a matriz para embaralhar.
fonte
No Swift 4.2 , agora existe um método para mutável
shuffle
e imutávelshuffled
. Você pode ler mais sobre as coisas aleatórias de geração e matriz aqui .fonte
É assim que você embaralha uma matriz com uma semente no Swift 3.0.
fonte
fonte
Isto é o que eu uso:
fonte
Exemplo simples:
fonte
Extensão de matriz de trabalho (com e sem mutação)
Swift 4.1 / Xcode 9
A resposta principal foi descontinuada, então decidi criar minha própria extensão para embaralhar uma matriz na versão mais recente do Swift, Swift 4.1 (Xcode 9):
Chamada aleatória sem mutação de chamada
[Array] -> [Array]
:Isso é impresso
array
em uma ordem aleatória.Aleatório de mutação de chamada
[Array] = [Array]
:Isso é impresso
array
em sua ordem atual, que já foi aleatoriamente embaralhada.Espero que isso funcione para todos, se você tiver quaisquer perguntas, sugestões ou comentários, não hesite em perguntar!
fonte
No SWIFT 4
fonte
Se você deseja usar a função de loop Swift For simples, use isto ->
Swift Array é suficiente usando a extensão ->
fonte
No Swift 4.2, existem duas funções úteis:
e
fonte
Aqui está um código que é executado no playground. Você não precisará importar o Darwin em um projeto real do Xcode.
fonte
drand48()
dá o mesmo pseudo números aleatórios toda vez que, a menos que você definir uma semente com gostosrand48(Int(arc4random()))
Ele pára em "swap (& self [i], & self [j])" quando atualizo a versão xCode para 7.4 beta.
erro fatal: a troca de um local consigo mesma não é suportada
Então eu adiciono uma condição como abaixo
YA! Tudo bem para mim.
fonte