web-dev-qa-db-ja.com

Swift switchステートメントの小なりまたは大

私はSwiftのswitchステートメントに精通していますが、このコードをswitchで置き換える方法を疑問に思っています:

if someVar < 0 {
    // do something
} else if someVar == 0 {
    // do something else
} else if someVar > 0 {
    // etc
}
117
Pieter

これが一つのアプローチです。 someVarIntまたは他のComparableであると仮定すると、オプションでオペランドを新しい変数に割り当てることができます。これにより、whereキーワードを使用してスコープを設定できます。

var someVar = 3

switch someVar {
case let x where x < 0:
    print("x is \(x)")
case let x where x == 0:
    print("x is \(x)")
case let x where x > 0:
    print("x is \(x)")
default:
    print("this is impossible")
}

これは少し単純化できます:

switch someVar {
case _ where someVar < 0:
    print("someVar is \(someVar)")
case 0:
    print("someVar is 0")
case _ where someVar > 0:
    print("someVar is \(someVar)")
default:
    print("this is impossible")
}

範囲一致でwhereキーワードを完全に回避することもできます。

switch someVar {
case Int.min..<0:
    print("someVar is \(someVar)")
case 0:
    print("someVar is 0")
default:
    print("someVar is \(someVar)")
}
201
Aaron Brager

Swift 5を使用すると、ifステートメントを置き換えるために、次のスイッチのいずれかを選択できます。


#1 PartialRangeFromおよびPartialRangeUpToでスイッチを使用する

let value = 1

switch value {
case 1...:
    print("greater than zero")
case 0:
    print("zero")
case ..<0:
    print("less than zero")
default:
    fatalError()
}

#2 ClosedRangeおよびRangeでスイッチを使用する

let value = 1

switch value {
case 1 ... Int.max:
    print("greater than zero")
case Int.min ..< 0:
    print("less than zero")
case 0:
    print("zero")
default:
    fatalError()
}

#3 where句でスイッチを使用する

let value = 1

switch value {
case let val where val > 0:
    print("\(val) is greater than zero")
case let val where val == 0:
    print("\(val) is zero")
case let val where val < 0:
    print("\(val) is less than zero")
default:
    fatalError()
}

#4 where句と_への割り当てでスイッチを使用する

let value = 1

switch value {
case _ where value > 0:
    print("greater than zero")
case _ where value == 0:
    print("zero")
case _ where value < 0:
    print("less than zero")
default:
    fatalError()
}

#5 RangeExpressionプロトコルの~=(_:_:)演算子でスイッチを使用する

let value = 1

switch true {
case 1... ~= value:
    print("greater than zero")
case ..<0 ~= value:
    print("less than zero")
default:
    print("zero")
}

#6 Equatableプロトコルの~=(_:_:)演算子でスイッチを使用する

let value = 1

switch true {
case value > 0:
    print("greater than zero")
case value < 0:
    print("less than zero")
case 0 ~= value:
    print("zero")
default:
    fatalError()
}

#7 PartialRangeFromPartialRangeUpTo、およびRangeExpressioncontains(_:)メソッドでスイッチを使用する

let value = 1

switch true {
case (1...).contains(value):
    print("greater than zero")
case (..<0).contains(value):
    print("less than zero")
default:
    print("zero")
}
73
Imanou Petit

内部のswitchステートメントは、~=演算子を使用します。したがって、この:

let x = 2

switch x {
case 1: print(1)
case 2: print(2)
case 3..<5: print(3..<5)
default: break
}

これに脱糖:

if 1          ~= x { print(1) }
else if 2     ~= x { print(2) }
else if 3..<5 ~= x { print(3..<5) }
else {  }

標準ライブラリリファレンスを見ると、~=がオーバーロードされていることを正確に伝えることができます :含まれているのは範囲の一致であり、等しいことを意味します。 (enum-caseマッチングは含まれていません。これは、std libの関数ではなく、言語機能です)

左側の真っ直ぐなブール値と一致しないことがわかります。この種の比較には、whereステートメントを追加する必要があります。

限り...... ~=演算子を自分でオーバーロードします。 (これは通常not推奨です)1つの可能性は次のようなものです:

func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
  return lhs(rhs)
}

そのため、左側のブール値を右側のパラメータに返す関数と一致します。使用できるものは次のとおりです。

func isEven(n: Int) -> Bool { return n % 2 == 0 }

switch 2 {
case isEven: print("Even!")
default:     print("Odd!")
}

あなたの場合、次のようなステートメントがあるかもしれません。

switch someVar {
case isNegative: ...
case 0: ...
case isPositive: ...
}

ただし、新しいisNegativeおよびisPositive関数を定義する必要があります。さらに演算子をオーバーロードしない限り...

通常の中置演算子をオーバーロードして、カリー化された前置演算子または後置演算子にすることができます。以下に例を示します。

postfix operator < {}

postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
  return lhs < rhs
}

これは次のように機能します。

let isGreaterThanFive = 5<

isGreaterThanFive(6) // true
isGreaterThanFive(5) // false

これを以前の関数と組み合わせると、switchステートメントは次のようになります。

switch someVar {
case 0< : print("Bigger than 0")
case 0  : print("0")
default : print("Less than 0")
}

さて、あなたはおそらく実際にはこの種のものを使うべきではありません:それは少し危険です。 (おそらく)whereステートメントにこだわる方が良いでしょう。とはいえ、switchステートメントパターンの

switch x {
case negative:
case 0:
case positive:
}

または

switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}

検討する価値があるほど十分に一般的と思われます。

18
oisdk

あなたはできる:

switch true {
case someVar < 0:
    print("less than zero")
case someVar == 0:
    print("eq 0")
default:
    print("otherwise")
}
12
rintaro

誰かがすでにcase let x where x < 0:を投稿しているので、ここでsomeVarIntの代わりになります。

switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}

そして、これはsomeVarDoubleである場合の代替です:

case -(Double.infinity)...0: // do something
// etc
6
simons

これは範囲でどのように見えるかです

switch average {
    case 0..<40: //greater or equal than 0 and less than 40
        return "T"
    case 40..<55: //greater or equal than 40 and less than 55
        return "D"
    case 55..<70: //greater or equal than 55 and less than 70
        return "P"
    case 70..<80: //greater or equal than 70 and less than 80
        return "A"
    case 80..<90: //greater or equal than 80 and less than 90
        return "E"
    case 90...100: //greater or equal than 90 and less or equal than 100
        return "O"
    default:
        return "Z"
    }
6
GOrozco58

<0式は機能しません(もう?)、私はこれで終わった:

Swift 3.0:

switch someVar {
    case 0:
        // it's zero
    case 0 ..< .greatestFiniteMagnitude:
        // it's greater than zero
    default:
        // it's less than zero
    }
3
Dorian Roy

Swift 4が問題に対処していることを嬉しく思います:3の回避策として:

switch translation.x  {
    case  0..<200:
        print(translation.x, slideLimit)
    case  -200..<0:
        print(translation.x, slideLimit)
    default:
        break
    }

機能するが理想的ではない

2
Jeremy Andrews