[Swift] 配列内をランダムにシャッフルする

2017.07.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

使う機会が多いかどうかはわかりませんが、配列の中身をランダムに入れ替えたいときもあるかもしれません。今回はその実装例を載せたいと思います。

extension

Array型のextensionを作成して以下のように実装します。

extension Array {

    mutating func shuffle() {
        for i in 0..<self.count {
            let j = Int(arc4random_uniform(UInt32(self.indices.last!)))
            if i != j {
                swap(&self[i], &self[j])
            }
        }
    }

    var shuffled: Array {
        var copied = Array<Element>(self)
        copied.shuffle()
        return copied
    }
}

shuffle() メソッドは自分自身の中身を入れ替えてしまいます。shuffled プロパティは自分自身の配列順は変更せずにシャッフルされた新しい配列を返します。

動作確認

shuffle() メソッドは mutating なので変数をvarにしてあげる必要があります。

print("// shuffle() のテスト")

var arr1 = [1,2,3,4,5,6,7,8,9,10]
arr1.shuffle()
print(arr1)
arr1.shuffle()
print(arr1)
print(arr1)

print("// shuffled のテスト")

let arr2 = [1,2,3,4,5,6,7,8,9,10]
print(arr2.shuffled)
print(arr2.shuffled)
print(arr2)

実行結果

// shuffle() のテスト
[10, 2, 9, 6, 7, 1, 5, 8, 3, 4]
[4, 8, 7, 9, 2, 5, 1, 10, 6, 3]
[4, 8, 7, 9, 2, 5, 1, 10, 6, 3]
// shuffled のテスト
[1, 6, 10, 5, 9, 2, 3, 7, 8, 4]
[7, 6, 10, 4, 9, 1, 5, 2, 3, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

shuffle() メソッドでは配列変数自体の中身が変わっていて、shuffled プロパティは配列変数自体の中身は変わっていないことを確認できると思います。