LoginSignup
31
26

More than 5 years have passed since last update.

Swiftのenum型の列挙子をfor inを使って列挙したい

Last updated at Posted at 2015-05-27

例えばこんな感じのenumを定義して

enum Fruit: Int {
    case Apple
    case Orange
    case Banana
}

この全ての列挙子(ここではAppleとOrangeとBanana)をfor inを使って列挙したくなったとする。どう考えてもfor fruit in [Fruit.Apple, Fruit.Orange, Fruit.Banana]なんてしたくない。

GeneratorOfを使って[Fruit]を返す

たどり着いたのがGeneratorOfを使って動的に[Fruit]を返すプロパティを生やすやり方。

enum Fruit: Int {
    case Apple
    case Orange
    case Banana

    static var fruits: [Fruit] {
        var index = 0
        return Array(
            GeneratorOf<Fruit> {
                return Fruit(rawValue: index++)
            }
        )
    }
}

for fruit in Fruit.fruits {
    println(fruit)
}

これはこれで覚えておくとして、もっとスマートなやり方があるのかないのか。というか、言語機能として列挙子返してくれないのかしら。

SequenceOfを使ってSequenceOf<Fruit>を返す

@satoshia さんのコメントより、こちらはSequenceOfを使ってSequenceOf<Fruit>を返却している。

static var fruits: SequenceOf<Fruit> {
    return SequenceOf { () -> GeneratorOf<Fruit> in
        var index = 0
        return GeneratorOf {
            Fruit(rawValue: index++)
        }
    }
}

配列を生成しない分スマートに見える。配列ではなくSequenceOf<Fruit>だけど、forで列挙する分には何ら問題ない。

自前で初期化して[Fruit]を返す

@takabosoft さんのコメントより。

static let fruits3: [Fruit] = [.Apple, .Orange, .Grape, .Berry, .Banana]

簡単だし、わかりやすいし、動的じゃない分パフォーマンスも良さそう。その反面、列挙漏れ・enumの宣言順が反映されない・追加や削除の度に更新しなくてはならないというリスクもある。とはいえ、列挙子の数が少なければこれでも良いような気も。

パフォーマンスの比較

予想通りの結果になった。SequenceOfGeneratorOfより若干遅いのは、配列を生成するしないに加えて、SequenceOf<Fruit>をループするのか[Fruit]をループするのかの差もあるのかと(予想だけど)。

enum-1.png

31
26
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
26