Swift

Swift: Enumからランダムに値を取得するExtension


どうも、ささおです。

Enumからランダムに値を取得するExtensionを書いていきます。

こちらの記事を参考にさせていただきました。
[Swift]enumでランダムなケースを返すextension

実装

Sampling というProtocolを作成し、ExtensionにgetSampleというランダムにEnumのcaseを取得する関数を実装します。

protocol Sampling {}

extension Sampling where Self: CaseIterable {
    static func getSample() -> Self {
      let all = self.allCases as! [Self]
      let index = Int.random(in: 0...all.count - 1)
      return all[index]
    }
}

 

1行ずつ解説

protocol Sampling {}

Samplingプロトコルを定義しています。

extension Sampling where Self: CaseIterable {

Samplingプロトコルのextensionで、
Self(Samplingプロトコルに準拠しているclassやenum)がCaseIterableにも準拠している場合に使えるextensionであることを書いています。

static func getSample() -> Self {

関数getSampleはSelf(Samplingプロトコルに準拠しているclassやenum)を返すことを定義しています。

let all = self.allCases as! [Self]

このextensionはCaseIterableに準拠している物しか使えないので、
extension内でallCasesを使うことができます。

allCasesはenumの全てのcaseを取得してくれます。
しかし、allCasesで取得できる値の型が Collection で、扱いづらいので、as! [Self] で配列にキャストしてあげます。

let index = Int.random(in: 0 all.count – 1)

Int.randomでランダム値を生成します。
引数に生成する範囲を指定できます。
このような形式です

Int.random(in: 範囲の始め...終わり)

all.count – 1している理由は、配列は0からはじまるからです。
仮にall.count が 4の場合は0 … 3の間で乱数を生成してほしいので1引いています。

実際に使う

今回はBloodTypeというenumを作成しました。
CaseIterableと、Samplingに準拠させます。

enum BloodType: CaseIterable, Sampling {
    case a
    case b
    case o
    case ab
}

あとは、呼び出すだけです。
print(BloodType.getSample())

 

全体のコード

public protocol Sampling {}

extension Sampling where Self: CaseIterable {
    static func getSample() -> Self {
        let all = self.allCases as! [Self]
        let index = Int.random(in: 0...all.count - 1)
        return all[index]
    }
}

enum BloodType: CaseIterable, Sampling {
    case a
    case b
    case o
    case ab
}

print(BloodType.getSample())

 

参考記事

[Swift]enumでランダムなケースを返すextension


ABOUT ME
ささお
3年目iOSエンジニア。 スタートアップで働いておりやす。 プログラミングスクールとエンジニアのキャリアを考えたい。 作ったアプリ - https://apps.apple.com/us/app/loverprofile/id1463563845?l=ja&ls=1