[解決済み】Swiftで配列をシャッフルするにはどうすればいいですか?
質問
Swift で配列内の要素をランダム化またはシャッフルするにはどうすればよいですか?たとえば、私の配列が52枚のトランプで構成されている場合、私は次のことをしたいです。 シャッフル を使用すると、デッキをシャッフルすることができます。
どのように解決するのですか?
この回答は、Swift 4.2+ で高速で均一なアルゴリズム (Fisher-Yates) でシャッフルする方法と、Swift の様々な以前のバージョンで同じ機能を追加する方法を詳細に説明します。各Swiftバージョンの命名と動作は、そのバージョンの変異と非変異のソートメソッドに一致します。
Swift 4.2+
shuffle
そして
shuffled
は Swift 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月からiTunes Connectでの公開にSwift 2.xを使用することはできません)
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月からiTunes Connectでの公開にSwift 1.xを使用することはできません)
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]
関連
-
[解決済み] Goではなぜリストがあまり使われないのですか?
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] 配列からArrayListを作成する
-
[解決済み] Java の配列を表示する最も簡単な方法は何ですか?
-
[解決済み] JavaScriptで配列の先頭に新しい配列要素を追加するにはどうすればよいですか?
-
[解決済み] JavaScriptのオブジェクトの配列からidでオブジェクトを検索する
-
[解決済み] JavaScriptの配列をランダム化(シャッフル)する方法は?
-
[解決済み】JavaScriptで2つの配列を結合し、項目の重複を排除する方法
-
[解決済み】要素を配列の先頭にプッシュする最も簡単な方法は何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン