Jak przetasować tablicę w Swift?

Jak losować lub tasować elementy w tablicy w Swift? Na przykład, jeśli moja tablica składa się z 52 kart do gry, chcę przetasować tablicę, aby przetasować talię.

Author: Cœur, 2014-06-04

25 answers

Ta odpowiedź opisuje jak przetasować za pomocą szybkiego i jednolitego algorytmu (Fisher-Yates) w Swift 4.2+ i jak dodać tę samą funkcję w różnych poprzednich wersjach Swift. Nazewnictwo i zachowanie dla każdej wersji Swift odpowiada metodom sortowania mutującego i niemutującego dla tej wersji.

Swift 4.2 +

shuffle oraz shuffled są natywne począwszy od Swift 4.2. Przykład użycia:

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 i 4.1

Te rozszerzenia dodają Metoda shuffle() do dowolnego zbioru mutowalnego (tablic i buforów mutowalnych) oraz metoda shuffled() do dowolnego ciągu:

extension MutableCollection {
    /// Shuffles the contents of this collection.
    mutating func shuffle() {
        let c = count
        guard c > 1 else { 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)
        }
    }
}

extension Sequence {
    /// Returns an array with the contents of this sequence, shuffled.
    func shuffled() -> [Element] {
        var result = Array(self)
        result.shuffle()
        return result
    }
}

Takie samo użycie jak w powyższych przykładach Swift 4.2.


Swift 3

Te rozszerzenia dodają metodę shuffle() do dowolnego zbioru zmiennego i metodę shuffled() do dowolnej sekwencji:

extension MutableCollection where Indices.Iterator.Element == Index {
    /// Shuffles the contents of this collection.
    mutating func shuffle() {
        let c = count
        guard c > 1 else { 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 != 0 else { continue }
            let i = index(firstUnshuffled, offsetBy: d)
            self.swapAt(firstUnshuffled, i)
        }
    }
}

extension Sequence {
    /// Returns an array with the contents of this sequence, shuffled.
    func shuffled() -> [Iterator.Element] {
        var result = Array(self)
        result.shuffle()
        return result
    }
}

Takie samo użycie jak w powyższych przykładach Swift 4.2.


Swift 2

(przestarzały język: nie możesz używać Swift 2.X do publikacji w iTunes Connect od lipca 2018)

extension MutableCollectionType 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 startIndex ..< endIndex - 1 {
            let j = Int(arc4random_uniform(UInt32(count - i))) + i
            guard i != j else { continue }
            swap(&self[i], &self[j])
        }
    }
}

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

Użycie:

[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

(przestarzały język: nie możesz używać Swift 1.x do publikacji w iTunes Connect od lipca 2018)

shuffle jako metoda mutacji tablicy

To rozszerzenie pozwoli Ci przetasować zmienną instancję Array w miejsce:

extension Array {
    mutating func shuffle() {
        if count < 2 { return }
        for i in 0..<(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 jako metoda nie mutująca tablicy

To rozszerzenie pozwoli Ci pobrać przetasowaną kopię instancji Array:

extension Array {
    func shuffled() -> [T] {
        if count < 2 { return self }
        var list = self
        for i in 0..<(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]
 544
Author: Nate Cook,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-07 05:49:33

Edit: Jak wspomniano w innych odpowiedziach, Swift 4.2 wreszcie dodaje generowanie liczb losowych do standardowej biblioteki, wraz z tasowaniem tablic.

Jednak GKRandom / GKRandomDistribution pakiet w GameplayKit nadal może być przydatny z nowym protokołem RandomNumberGenerator - jeśli dodasz rozszerzenia do GameplayKit RNGs, aby były zgodne z nowym standardowym protokołem bibliotecznym, możesz łatwo uzyskać:

  • sendable RNGs (które mogą odtworzyć" losową " sekwencję w razie potrzeby dla testowanie)
  • RNGs, które poświęcają solidność dla prędkości
  • RNGs, które wytwarzają rozkłady niejednorodne

...i nadal korzystaj z ładnych nowych" natywnych " losowych interfejsów API w języku Swift.

Reszta tej odpowiedzi dotyczy takich RNG i / lub ich wykorzystania w starszych kompilatorach Swift.


Jest tu już kilka dobrych odpowiedzi, a także kilka dobrych ilustracji, dlaczego pisanie własnego shuffle może być podatne na błędy, jeśli nie jesteś ostrożny.

W iOS 9, macOS 10.11 i tvOS 9 (lub nowszy), nie musisz pisać własnych. W GameplayKit jest skuteczna, poprawna implementacja Fisher-Yates (która, wbrew nazwie, nie jest przeznaczona tylko do gier).

Jeśli chcesz tylko unikatowego shuffle:

let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
Jeśli chcesz być w stanie replikować tasowanie lub serię tasowań, wybierz i zasiewaj określone losowe źródło, np.]}
let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)

W iOS 10 / macOS 10.12 / tvOS 10 istnieje również wygodna składnia tasowania za pomocą rozszerzenie na NSArray. Oczywiście, jest to trochę kłopotliwe, gdy używasz Swift Array (i traci swój Typ elementu po powrocie do Swift):

let shuffled1 = (array as NSArray).shuffled(using: random) // -> [Any]
let shuffled2 = (array as NSArray).shuffled() // use default random source

Ale dość łatwo jest zrobić dla niego owijarkę Swift zachowującą Typ:

extension Array {
    func shuffled(using source: GKRandomSource) -> [Element] {
        return (self as NSArray).shuffled(using: source) as! [Element]
    }
    func shuffled() -> [Element] {
        return (self as NSArray).shuffled() as! [Element]
    }
}
let shuffled3 = array.shuffled(using: random)
let shuffled4 = array.shuffled()
 127
Author: rickster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 01:06:43

W Swift 2.0 GameplayKit może przyjść na ratunek! (obsługiwane przez iOS9 lub nowszy)

import GameplayKit

func shuffle() {
    array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}
 29
Author: bluenowhere,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-17 05:53:12

Tu jest coś chyba trochę krótszego:

sorted(a) {_, _ in arc4random() % 2 == 0}
 26
Author: Jean Le Moignan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-06 02:46:19

Biorąc algorytm Nate ' a chciałem zobaczyć jak to będzie wyglądać z Swift 2 i rozszerzeniami protokołu.

To właśnie wymyśliłem.
extension MutableCollectionType where Self.Index == Int {
    mutating func shuffleInPlace() {
        let c = self.count
        for i in 0..<(c - 1) {
            let j = Int(arc4random_uniform(UInt32(c - i))) + i
            swap(&self[i], &self[j])
        }
    }
}

extension MutableCollectionType where Self.Index == Int {
    func shuffle() -> Self {
        var r = self
        let c = self.count
        for i in 0..<(c - 1) {
            let j = Int(arc4random_uniform(UInt32(c - i))) + i
            swap(&r[i], &r[j])
        }
        return r
    }
}

Teraz każdy {[1] } może używać tych metod, ponieważ używa Int jako Index

 7
Author: Chris Wagner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:32

W moim przypadku miałem problemy z zamianą obiektów w tablicy. Podrapałam się biedna po brodzie

// swift 3.0 ready
extension Array {

    func shuffled() -> [Element] {
        var results = [Element]()
        var indexes = (0 ..< count).map { $0 }
        while indexes.count > 0 {
            let indexOfIndexes = Int(arc4random_uniform(UInt32(indexes.count)))
            let index = indexes[indexOfIndexes]
            results.append(self[index])
            indexes.remove(at: indexOfIndexes)
        }
        return results
    }

}
 6
Author: Kaz Yoshikawa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-24 04:46:33

Jest to wersjaimplementacji Fisher-Yates shuffle dla Swift 4 (Xcode 9).

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

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

Zmiany są następujące:

  • ograniczenie Indices.Iterator.Element == Index jest teraz częścią protokołu Collection i nie muszą być nakładane na / align = "left" /
  • wymiana elementów musi odbywać się poprzez wywołanie swapAt() na zbiorze, porównaj SE-0173 dodaj MutableCollection.swapAt(_:_:).
  • Element jest aliasem dla Iterator.Element.
 4
Author: Martin R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 09:32:04

Tego używam:

func newShuffledArray(array:NSArray) -> NSArray {
    var mutableArray = array.mutableCopy() as! NSMutableArray
    var count = mutableArray.count
    if count>1 {
        for var i=count-1;i>0;--i{
            mutableArray.exchangeObjectAtIndex(i, withObjectAtIndex: Int(arc4random_uniform(UInt32(i+1))))
        }
    }
    return mutableArray as NSArray
}
 3
Author: iliketopgun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-09 14:43:47

Swift 4 Shuffle elementy tablicy w pętli for gdzie i jest współczynnikiem mieszania

var cards = [Int]() //Some Array
let i = 4 // is the mixing ratio
func shuffleCards() {
    for _ in 0 ..< cards.count * i {
        let card = cards.remove(at: Int(arc4random_uniform(UInt32(cards.count))))
        cards.insert(card, at: Int(arc4random_uniform(UInt32(cards.count))))
    }
}

Lub z rozszerzeniem Int

func shuffleCards() {
    for _ in 0 ..< cards.count * i {
        let card = cards.remove(at: cards.count.arc4random)
        cards.insert(card, at: cards.count.arc4random)
    }
}
extension Int {
    var arc4random: Int {
        if self > 0 {
            print("Arc for random positiv self \(Int(arc4random_uniform(UInt32(self))))")
        return Int(arc4random_uniform(UInt32(self)))
        } else if self < 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")
            return 0
        }
    }
}
 3
Author: Sergei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-03 09:22:32

Swift 3 rozwiązanie, po @ Nate Cook odpowiedź: (praca, jeśli indeks zaczyna się od 0, Zobacz komentarze poniżej)

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

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 }
        let countInt = count as! Int

    for i in 0..<countInt - 1 {
        let j = Int(arc4random_uniform(UInt32(countInt - i))) + i
            guard i != j else { continue }
            swap(&self[i], &self[j])
        }
    }
}
 2
Author: Anson Yao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-17 05:00:59

Tak to się robi w najprostszy sposób.import Gamplaykit do swojego VC i użyj poniższego kodu. Testowane w Xcode 8.

 import GameplayKit

 let array: NSArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]

 override func viewDidLoad() {
    super.viewDidLoad()

    print(array.shuffled())  
}

Jeśli chcesz uzyskać tasowany ciąg znaków z tablicy, możesz użyć poniższego kodu..

func suffleString() {

    let ShuffleArray = array.shuffled()

    suffleString.text = ShuffleArray.first as? String

    print(suffleString.text!)

}
 2
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-04 13:22:40

W Swift 3, Jeśli chcesz przetasować tablicę lub uzyskać nową tablicę z tablicy, AnyIterator mogę ci pomóc. Chodzi o to, aby utworzyć tablicę indeksów z tablicy, aby przetasować te indeksy za pomocą instancji AnyIterator i swap(_:_:) funkcja i odwzorowanie każdego elementu tej instancji AnyIterator z odpowiadającym jej elementem tablicy.


Poniższy kod placu zabaw pokazuje jak to działa:

import Darwin // 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 {
    guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
        else { return nil }

    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"]

Możesz refaktorować poprzedni kod i tworzenie funkcji shuffled() wewnątrz rozszerzenia Array w celu uzyskania nowej tasowanej tablicy z tablicy:

import Darwin // required for arc4random_uniform

extension Array {

    func shuffled() -> Array<Element> {
        var indexArray = Array<Int>(indices)        
        var index = indexArray.endIndex

        let indexIterator = AnyIterator<Int> {
            guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
                else { return nil }

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

}

użycie:

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: []

Jako alternatywę dla poprzedniego kodu, możesz utworzyć funkcję shuffle() wewnątrz rozszerzenia Array w celu przetasowania tablicy w miejscu:

import Darwin // required for arc4random_uniform

extension Array {

    mutating func shuffle() {
        var indexArray = Array<Int>(indices)
        var index = indexArray.endIndex

        let indexIterator = AnyIterator<Int> {
            guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
                else { return nil }

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

}

użycie:

var mutatingArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen", "Pamela", "Jock", "Ellie", "Bobby", "JR"]
 2
Author: Imanou Petit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-27 10:50:00

Stwórz artykuł Fisher-Yates shuffle na Wikipedii

Swift 3.1,4.0

A). Metoda ołówkowo-papierowa:

func shuffle<T>(_ array:inout [T]){

    var temp = [T]()

    for _  in array{

        /*Generating random number with length*/
        let random = arc4random_uniform(UInt32(array.count))
        /*Take the element from array*/
        let elementTaken = array[Int(random)]
        /*Append it to new tempArray*/
        temp.append(elementTaken)
        /*Remove the element from array*/
        array.remove(at: Int(random))

    }
    /* array = tempArray*/
    array = temp
}

B). Metoda współczesna: (Wersja Durstenfelda)

func shuffle<T>(_ array:inout [T]){

    var length = array.count

    for _  in array{

        /*Generating random number with length*/
        let random = arc4random_uniform(UInt32(length))
        /*Check before index of two elements not same*/
        if length-1 != Int(random){
            swap(&array[length-1], &array[Int(random)])
        }

        length -= 1
    }
}

Extension:

A). Metoda ołówkowo-papierowa:

extension Array{

    mutating func shuffled(){

        var temp = [Element]()

        for _  in self{

            /*Generating random number with length*/
            let random = arc4random_uniform(UInt32(self.count))
            /*Take the element from array*/
            let elementTaken = self[Int(random)]
            /*Append it to new tempArray*/
            temp.append(elementTaken)
            /*Remove the element from array*/
            self.remove(at: Int(random))

        }
        /* array = tempArray*/
        self = temp
    }
}

B). Metoda współczesna: (Wersja Durstenfelda)

extension Array{

    mutating func shuffled(){

        var length = self.count

        for _  in self{

            /*Generating random number with length*/
            let random = arc4random_uniform(UInt32(length))

            /*Check before index of two elements not same*/

            if length-1 != Int(random){

                /*Swaping elements, If same index then there is no swap*/
               // swap(&self[length-1], &self[Int(random)]) -> Swift 3.0
                self.swapAt(length-1, Int(random)) //-> Swift 4.0

            }

            length -= 1
        }
    }
}

Numer referencyjny:

/* By using shuffle functions*/
var a = [1,2,3,4,5,6,7,8,9,10]

for _ in 1...10{

    self.shuffle(&a)

    /*For shuffled extension, a.shuffled()*/
    print(a)
}

Uwaga: Możesz użyj również pustej tablicy.

Wyjście:

[6, 2, 10, 5, 1, 8, 9, 4, 3, 7]

[7, 1, 9, 8, 2, 10, 5, 6, 4, 3]

[8, 9, 6, 10, 5, 2, 7, 4, 3, 1]

[10, 1, 7, 4, 8, 9, 3, 5, 2, 6]

[8, 1, 6, 9, 3, 7, 4, 5, 10, 2]

[4, 3, 7, 9, 1, 5, 8, 6, 10, 2]

[7, 3, 4, 9, 10, 1, 6, 5, 2, 8]

[3, 6, 2, 4, 5, 8, 9, 7, 1, 10]

[5, 1, 2, 10, 6, 9, 7, 3, 8, 4]

[7, 9, 3, 8, 2, 1, 5, 4, 6, 10]

Proszę dać mi znać, jeśli jakieś pytania, inna wersja Swift będzie wkrótce sprawdzić.

 2
Author: Rajamohan S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-16 04:55:43

Możesz również użyć funkcji generic swap i zaimplementować wspomnianą funkcję Fisher-Yates:

for idx in 0..<arr.count {
  let rnd = Int(arc4random_uniform(UInt32(idx)))
  if rnd != idx {
    swap(&arr[idx], &arr[rnd])
  }
}

Lub mniej wyrazisty:

for idx in 0..<steps.count {
  swap(&steps[idx], &steps[Int(arc4random_uniform(UInt32(idx)))])
}
 1
Author: Daniel Bauke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-03 11:30:04

Działa!!. organizmy są tablicą do przetasowania.

extension Array
{
    /** Randomizes the order of an array's elements. */
    mutating func shuffle()
    {
        for _ in 0..<10
        {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}

var organisms = [
    "ant",  "bacteria", "cougar",
    "dog",  "elephant", "firefly",
    "goat", "hedgehog", "iguana"]

print("Original: \(organisms)")

organisms.shuffle()

print("Shuffled: \(organisms)")
 1
Author: Vimal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-08 10:06:42

Oto jak przetasować jedną tablicę z ziarnem w Swift 3.0.

extension MutableCollection where Indices.Iterator.Element == Index {
    mutating func shuffle() {
        let c = count
        guard c > 1 else { return }


        for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
            srand48(seedNumber)
            let number:Int = numericCast(unshuffledCount)
            let r = floor(drand48() * Double(number))

            let d: IndexDistance = numericCast(Int(r))
            guard d != 0 else { continue }
            let i = index(firstUnshuffled, offsetBy: d)
            swap(&self[firstUnshuffled], &self[i])
        }
    }
}
 0
Author: Tayo119,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-15 09:41:43
let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)
 0
Author: Rohit Sisodia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-05 10:14:11

Tego używam:

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]
 0
Author: Daniel Illescas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-24 20:45:01

Prosty Przykład:

extension Array {
    mutating func shuffled() {
        for _ in self {
            // 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]
 0
Author: Bobby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-02 17:34:45

Working Array Extension (mutating & non-mutating)

Swift 4.1 / Xcode 9

Najlepsza odpowiedź jest przestarzała, więc wziąłem na siebie, aby stworzyć własne rozszerzenie do shuffle tablicy w najnowszej wersji Swift, Swift 4.1 (Xcode 9):

extension Array {

// Non-mutating shuffle
    var shuffled : Array {
        let totalCount : Int = self.count
        var shuffledArray : Array = []
        var count : Int = totalCount
        var tempArray : Array = self
        for _ in 0..<totalCount {
            let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
            let randomElement : Element = tempArray.remove(at: randomIndex)
            shuffledArray.append(randomElement)
            count -= 1
        }
        return shuffledArray
    }

// Mutating shuffle
    mutating func shuffle() {
        let totalCount : Int = self.count
        var shuffledArray : Array = []
        var count : Int = totalCount
        var tempArray : Array = self
        for _ in 0..<totalCount {
            let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
            let randomElement : Element = tempArray.remove(at: randomIndex)
            shuffledArray.append(randomElement)
            count -= 1
        }
        self = shuffledArray
    }
}

Call Non-Mutating Shuffle [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)

To drukuje array w losowej kolejności.


Wywołanie Mutacji Shuffle [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) 

To drukuje array w bieżącej kolejności, która już zostały przypadkowo przetasowane.


Mam nadzieję, że to działa dla wszystkich, jeśli masz jakieś pytania, sugestie lub komentarze, nie krępuj się pytać!

 0
Author: Noah Wilder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-21 16:14:12

W SWIFT 4

func createShuffledSequenceOfNumbers(max:UInt)->[UInt] {

    var array:[UInt]! = []
    var myArray:[UInt]! = []
    for i in 1...max {
        myArray.append(i)
    }
    for i in 1...max {
        array.append(i)
    }
    var tempArray:[Int]! = []
    for index in 0...(myArray.count - 1) {

        var isNotFinded:Bool = true
        while(isNotFinded){

            let randomNumber = arc4random_uniform(UInt32(myArray.count))
            let randomIndex = Int(randomNumber)

            if(!tempArray.contains(randomIndex)){
                tempArray.append(randomIndex)

                array[randomIndex] = myArray[index]
                isNotFinded = false
            }
        }
    }

    return array
}
 0
Author: ali khezri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-17 07:52:30

W Swift 4.2 , istnieje obecnie metoda dla obu mutowalnych shuffle i niezmienne shuffled. Możesz przeczytać więcej o random generation and array stuff tutaj .

 0
Author: leogdion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-07 05:31:38

Jeśli chcesz użyć simple Swift dla funkcji loop użyj tego- >

var arrayItems = ["A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "X9", "Y10", "Z11"]
var shuffledArray = [String]()

for i in 0..<arrayItems.count
{
    let randomObject = Int(arc4random_uniform(UInt32(items.count)))

    shuffledArray.append(items[randomObject])

    items.remove(at: randomObject)
}

print(shuffledArray)

Swift Array suffle using extension - >

extension Array {
    // Order Randomize
    mutating func shuffle() {
        for _ in 0..<count {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}
 0
Author: Rahul Singha Roy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-27 10:48:13

Oto jakiś kod, który działa na placu zabaw. Nie musisz importować Darwina do rzeczywistego projektu Xcode.

import darwin

var a = [1,2,3,4,5,6,7]

func shuffle<ItemType>(item1: ItemType, item2: ItemType) -> Bool {
    return drand48() > 0.5
}

sort(a, shuffle)

println(a)
 -2
Author: Dan Hixon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-04 00:48:40

Zatrzymuje się na " swap (&self[i], & self[j])", gdy uaktualnię wersję xCode do 7.4 beta.
w tym celu prosimy o zapoznanie się z naszą polityką prywatności.]}

Znalazłem powód, dla którego i = j (funkcja swap eksploduje)

Więc dodaję warunek jak poniżej

if (i != j){
    swap(&list[i], &list[j])
}
YA! Dla mnie jest OK.
 -3
Author: 米米米,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-26 03:27:06