Swiftで配列をシャッフルするにはどうすればよいですか?


305

Swiftで配列内の要素をランダム化またはシャッフルするにはどうすればよいですか?たとえば、私の配列が52枚のトランプで構成されている場合、デッキをシャッフルするために配列をシャッフルしたいと思います。


2
これは特定の言語に固有のものではありません。シャッフルアルゴリズムを適用するだけ
ガブリエレペトロネラ2014年

8
@Mithrandirそれは本当ではない。Rubyではに行くでしょうarray.shuffle。独自のバージョンを実装する必要はありません。OPは似たようなものを探していたと思います。
Linus Oleander 14年

1
ただし、カードデッキをシャッフルするためにシャッフルアルゴリズムだけを使用しないでください。
njzk2

回答:


627

この回答では、Swift 4.2以降で高速かつ均一なアルゴリズム(Fisher-Yates)でシャッフルする方法と、以前のバージョンのSwiftで同じ機能を追加する方法について詳しく説明します。各Swiftバージョンの命名と動作は、そのバージョンの変更および非変更ソート方法と一致します。

Swift 4.2以降

shuffleそしてshuffledスウィフト4.2起動ネイティブです。使用例:

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および4.1

これらの拡張機能は、shuffle()任意の可変コレクション(配列および安全でない可変バッファー)にメソッドを追加し、shuffled()任意のシーケンスにメソッドを追加します。

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

上記のSwift 4.2の例と同じ使用法。


スウィフト3

これらの拡張機能は、shuffle()任意の可変コレクションにメソッドを追加し、shuffled()任意のシーケンスにメソッドを追加します。

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

上記のSwift 4.2の例と同じ使用法。


スウィフト2

(廃止された言語:2018年7月以降、Swift 2.xを使用してiTunes Connectで公開することはできません)

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

使用法:

[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

(廃止された言語:2018年7月以降、Swift 1.xを使用してiTunes Connectで公開することはできません)

shuffle 変異配列メソッドとして

この拡張機能を使用すると、変更可能なArrayインスタンスを適切にシャッフルできます。

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 非変異配列メソッドとして

この拡張機能により、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]

1
Swift 1.2の関数バージョンが必要な場合は、このまま少し更新する必要があります。countElements代わりにcount、が返されるT.Index.Distanceため、制約をオンにする必要がありますC.Index.Distance == Int。このバージョンは機能するはずです:gist.github.com/airspeedswift/03d07a9dc86fabdc370f
Airspeed Velocity

2
これらは実際の出力です。Fisher-Yatesはソースの不偏ランダム置換を返す必要があるため、特定の要素を移動する必要はありません。そこである保証はありませんその要素を移動する複数回、時には「移動」とは、同じインデックスにあります。最も単純なケースは考えることです— [1, 2].shuffled()それは[2, 1]毎回戻る必要がありますか?
ネイト・クック

1
if count > 0空の配列が渡されたときに「致命的エラー:範囲<終了<開始で範囲を形成できません "を受信しないように、可変配列関数の上部に追加しました。
Carl Smith

3
@Jan:はい、guard i != j else { continue }スワップの前に追加します。私はレーダーを提出しましたが、新しい行動は意図的です。
Nate Cook、

3
shuffleInPlace配列のスライスなど、コレクションのインデックスがゼロから始まらない場合、実際にはクラッシュする可能性があります。for i in 0..<count - 1 でなければならないfor i in startIndex ..< endIndex - 1(そしてスウィフト3への変換は、ほとんど自明となります)。
Martin R

131

編集:他の回答で述べたように、最終的にSwift 4.2乱数生成を標準ライブラリ追加し、配列のシャッフルを完了します。

ただし、GameplayKit のGKRandom/ GKRandomDistributionスイートは新しいRandomNumberGeneratorプロトコルでも引き続き使用できます。GameplayKitRNGに拡張機能を追加して新しい標準ライブラリプロトコルに準拠させると、次のように簡単に取得できます。

  • 送信可能なRNG(テストに必要なときに「ランダムな」シーケンスを再現できる)
  • スピードのために堅牢性を犠牲にするRNG
  • 不均一な分布を生成するRNG

...そして、Swiftの新しい「ネイティブ」ランダムAPIを引き続き利用します。

この回答の残りは、そのようなRNGや古いSwiftコンパイラでのそれらの使用に関係しています。


ここにはすでにいくつかの良い答えがあります。注意しないと、独自のシャッフルを書くとエラーが発生しやすくなる理由を示す良いイラストもあります。

iOS 9、macOS 10.11、およびtvOS 9(以降)では、独自に記述する必要はありません。ありますフィッシャーイエーツの効率的な、正しい実装は、(名前にもかかわらず、ゲームのためだけのものではありません、)GameplayKitでは。

ユニークなシャッフルが必要な場合:

let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)

シャッフルまたは一連のシャッフルを複製できるようにする場合は、特定のランダムソースを選択してシードします。例えば

let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)

iOS 10 / macOS 10.12 / tvOS 10には、の拡張機能を介してシャッフルするための便利な構文もありますNSArray。もちろん、Swiftを使用している場合は少し面倒ですArray(Swiftに戻ると要素タイプが失われます)。

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

しかし、型を保持するSwiftラッパーを作成するのは非常に簡単です。

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

6
私がこれまで探索したことがない他の有用なユーティリティがGameplayKitにあるのか疑問に思います!
Richard Venable 2015年

6
グラフ検索、ツリー検索、ルールシステム... ゲームデザインやその他の面で役立つ多くの機能
rickster

5
スウィフト3 / iOSの10で、これは次のように変更されました:let shuffled = lcg.arrayByShufflingObjects(in: array)
エヴァン・ポン

30

スウィフト2.0、GameplayKitが救助に来るかもしれません!(iOS9以降でサポート)

import GameplayKit

func shuffle() {
    array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}

5
シャッフルされた配列を取得するためだけにGameplayKitをインポートすることは素晴らしいアイデアのようには聞こえません
Lope

3
どうして?システムの一部であり、バイナリに追加されません。
Abizern 2017年

3
また、インポートのスコープを単純にすることもできますimport GameplayKit.GKRandomSource
JRG-Developer

26

これはおそらく少し短いものです:

sorted(a) {_, _ in arc4random() % 2 == 0}

1
@moby sort関数は要素を順序付けるためにクロージャーを必要とします。このクロージャーは2つのパラメーター(elem1、elem2)を取り、最初の値が2番目の値の前に現れる場合はtrueを返し、そうでない場合はfalseを返す必要があります。代わりにランダムなブール値を返す場合...次に、全体を混同します:)
Jean Le Moignan '

2
ここで確認または反証する数学者はいますか?
Jean Le Moignan、2014

9
pjsが別の非常に類似した回答に応じて指摘したように、これは結果の均一な分布を生成しませんネイトクックの回答に示すように、Fisher-Yates Shuffleを使用します。
Rob

1
これは巧妙なトリックですが、シャッフルの品質の面でひどいです。1 arc4random_uniform()つには、このクロージャは現在モジュロバイアスの影響を受けているため、を使用する必要があります。第二に、出力はソートアルゴリズムに非常に強く依存します(これはソースを確認しないとわかりません)。
アレクサンダー-モニカ

1
このより単純なアプローチを続けると、これは非常にうまく機能するようです: collection.sorted { _,_ in arc4random_uniform(1) == 0 }
markiv

7

撮影ネイトのアルゴリズムを私はこれがスウィフト2およびプロトコル拡張でどのように見えるかを見てみたかったです。

これが私が思いついたものです。

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

さて、任意のは、MutableCollectionTypeそれが使用する与えられたこれらのメソッドを使用することができますIntようにIndex


6

私の場合、配列内のオブジェクトを交換する際にいくつかの問題がありました。それから私は頭を掻いて、車輪を再発明しに行きました。

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

}

5

これは、NwiによるSwift 4 (Xcode 9)向けのFisher-Yatesシャッフルの実装バージョンです。

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

変更点は次のとおりです。

  • 制約Indices.Iterator.Element == IndexCollectionプロトコルの一部になり、もはや拡張に課される必要はありません。
  • 要素の交換swapAt()は、コレクションを呼び出して行う必要があります。SE-0173AddMutableCollection.swapAt(_:_:)と比較してください
  • ElementのエイリアスですIterator.Element

3

これは私が使用するものです:

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

Swift 4 forループで配列の要素をシャッフルします(iは混合比です)

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

または拡張子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
        }
    }
}

2

@Nate Cookの回答に従ったSwift 3ソリューション:(インデックスが0で始まる場合は機能します。以下のコメントを参照してください)

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

1
これは、たとえば配列スライスの場合など、コレクションインデックスが0から始まる場合にクラッシュする可能性があります。var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace()数回実行してみてください。– 正しい解決策については、stackoverflow.com / a / 37843901/1187415を参照してください。
Martin R

2

これが最も簡単な方法で行われる方法です。import GamplaykitあなたのVCに以下のコードを使用してください。Xcode 8でテスト済み。

 import GameplayKit

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

 override func viewDidLoad() {
    super.viewDidLoad()

    print(array.shuffled())  
}

配列からシャッフルされた文字列を取得したい場合は、以下のコードを使用できます。

func suffleString() {

    let ShuffleArray = array.shuffled()

    suffleString.text = ShuffleArray.first as? String

    print(suffleString.text!)

}

2

Swift 3では、配列を所定の位置に入れ替えたり、配列から新しい配列を取得したりAnyIteratorする場合に役立ちます。アイデアは、配列からインデックスの配列を作成し、それらのインデックスをAnyIteratorインスタンスとswap(_:_:)関数でシャッフルし、このAnyIteratorインスタンスの各要素を配列の対応する要素にマップすることです。


次のPlaygroundコードは、その仕組みを示しています。

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

以前のコードをリファクタリングしshuffled()Array拡張機能内に関数を作成して、配列から新しいシャッフルされた配列を取得できます。

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

}

使用法:

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

前のコードの代わりに、配列を所定の位置に入れ替えるためにshuffle()Array拡張機能内に関数を作成できます。

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

}

使用法:

var mutatingArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen", "Pamela", "Jock", "Ellie", "Bobby", "JR"]

1

ジェネリックswap関数も使用でき、前述のフィッシャーイェイツを実装できます。

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

以下の冗長:

for idx in 0..<steps.count {
  swap(&steps[idx], &steps[Int(arc4random_uniform(UInt32(idx)))])
}

2
これは、少なくとも、ここで説明されている1つのエラーによる深刻な問題に悩まされています。これにより、値は常に元の位置から交換されます。これはで改善されlet rnd = Int(arc4random_uniform(UInt32(idx + 1)))ます。また、FYでは、通常、arr.count - 1down 1から0toまで反復します(またはto から反復する場合arr.count - 1は、Nateが受け入れられた回答で示すようにインデックスを選択します)。フィッシャーイェイツの議論の現代アルゴリズムのセクションを参照してください。
Rob

1

動作します。生物はシャッフルする配列です。

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


0

これは、Swift 3.0で1つの配列をシードでシャッフルする方法です。

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

これは私が使用するものです:

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

簡単な例:

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

ワーキングアレイエクステンション(変異および非変異)

Swift 4.1 / Xcode 9

一番上の答えは非推奨であるため、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
    }
}

非ミューテーションシャッフルを呼び出す[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)

これarrayはランダムな順序で印刷されます。


ミューティングシャッフルの呼び出し[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) 

これarrayは、すでにランダムにシャッフルされている現在の順序で印刷されます。


これがすべての人にとってうまくいくことを願っています。質問、提案、コメントがある場合は、遠慮なく質問してください!


0

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

単純なSwift Forループ関数を使用したい場合は、これを使用してください->

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配列のシャッフル->

extension Array {
    // Order Randomize
    mutating func shuffle() {
        for _ in 0..<count {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}

0

Swift 4.2以降、2つの便利な関数があります。

// shuffles the array in place
myArray.shuffle()

そして

// generates a new array with shuffled elements of the old array
let newArray = myArray.shuffled()

-2

遊び場で実行されるコードをいくつか示します。実際のXcodeプロジェクトにDarwinをインポートする必要はありません。

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)

7
これにより、結果の分布が不均一になります。これはO(n log n)にもなり、Fisher-YatesシャッフルはO(n)時間で均一に分散された結果を提供します。
pjs

drand48()likeを使用してシードを設定しない限り、毎回同じ擬似乱数も提供しますsrand48(Int(arc4random()))
Kametrixom

-3

xCodeのバージョンを7.4ベータにアップグレードすると、「swap(&self [i]、&self [j])」で停止します。
致命的なエラー:場所自体とのスワップはサポートされていません

i = jの理由を見つけました(スワップの関数が爆発します)

以下のように条件を追加します

if (i != j){
    swap(&list[i], &list[j])
}

Y A!私には大丈夫です。


これは、Chrisの回答に対するコメントのようであり、元の質問に対する回答ではありません。
Mogsdad 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.