web-dev-qa-db-ja.com

複数の「if case」ステートメントで「or」ロジックを使用する

関連する値を持つ列挙型のケースと、その列挙型の2つの変数があるとします。

enum MyEnum {
    case foo, bar(_ prop: Int)
}

let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)

both変数が一般的なケースと関連する値と一致するかどうかを確認する場合は、コンマを使用して実行できます。

if case .bar = var1, case .bar = var2 {
    print("both are bar")
}

しかし、-どちらかが大文字と小文字が一致するかどうかを確認する必要があります。

if case .bar = var1 || case .bar = var2 {
    print("at least one is bar")
}

ただし、これはコンパイルされません。これを記述してロジックを機能させる別の方法はありますか?

10
John Montgomery

「aまたはb」テストを読みやすくするために、列挙型自体のある種のisBarプロパティを使用します。

enum MyEnum {
    case foo, bar(_ prop: Int)

    var isBar: Bool {
        switch self {
        case .bar: return true
        default: return false
        }
    }
}

let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)

let eitherIsBar = var1.isBar || var2.isBar
8
Gereon

列挙型にはEquatableプロトコルを実装する必要があります。

extension MyEnum: Equatable {}
func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
    switch (lhs, rhs) {
        case (let .bar(prop1), let .bar(prop2)):
            return prop1 == prop2
        case (.foo, .foo):
        return true

     default:
         return false
    }
}

その後、次のコードが機能するはずです。

if var1 == .bar(1) || var2 == .bar(1) {
    print("at least one is bar")
}

UPD:関連付けられた値を確認する必要がない場合は、次のようなパターンマッチングを実行できます。

switch (var1, var2) {
case (.bar, _), (_, .bar): print("at least one is bar")
default: break
}
3
kovpas

この種のものに対する私の解決策は:

if [var1、var2] .contains(.bar){

多くの場合、私はそれを別の方法で望んでいます、いくつかの値に基づいてフィルタリングされる単一の変数:

if [.bar、.baz] .contains(var)

しかし、実際には、関連する値が含まれている場合は、それらを赤道化し、演算子を定義する必要があります。

1
Phill Apley

私の推測では、if caseguard caseはシンタックスシュガーであり、開発者のエクスペリエンスを向上させるためにコンパイラでサポートされている小さな機能にすぎません。最初のケースでは、連続条件を使用しています。これは、&&演算子を置き換えてコードを読みやすくするための言語機能でもあります。 &&または||演算子を使用している場合、コンパイラーはブール値を返す2つの式を取得することを期待します。 case .bar = var1自体は、Swiftのコンテキストがなければ、単独で存在できる式ではないため、ブール値を返す式として扱われません。

要約すると:

  • if caseguard caseは単なるシンタックスシュガーであり、if <expression>, <expression>構文と連携して機能します

  • &&||は、論理演算子であり、基本的には両側に2つのブール引数を必要とする関数です。

問題を解決するには、古き良きswitchステートメントを使用します。それが役に立てば幸い。

0
witek bobrowski