web-dev-qa-db-fra.com

Inférieur ou supérieur à dans l'instruction Swift switch

Je connais bien les instructions switch dans Swift, mais je me demande comment remplacer ce code par un switch:

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

Voici une approche. En supposant que someVar soit un Int ou un autre Comparable, vous pouvez éventuellement affecter l'opérande à une nouvelle variable. Cela vous permet de le définir comme vous le souhaitez à l'aide du mot clé 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")
}

Cela peut être simplifié un peu:

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")
}

Vous pouvez également éviter le mot clé where avec la correspondance de plage:

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

Avec Swift 5, vous pouvez choisir l’un des commutateurs suivants pour remplacer votre instruction if.


# 1 Utilisation du commutateur avec PartialRangeFrom et 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 Utilisation du commutateur avec ClosedRange et 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 Utilisation de switch avec la clause 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 Utilisation de switch avec une clause where et affectation à _

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 Utilisation du commutateur avec l'opérateur ~=(_:_:) du protocole RangeExpression

let value = 1

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

# 6 Utilisation d'un commutateur avec l'opérateur ~=(_:_:) du protocole 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 Utilisation du commutateur avec la méthode PartialRangeFrom, PartialRangeUpTo et 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")
}
81
Imanou Petit

L'instruction switch, sous le capot, utilise l'opérateur ~=. Donc ça:

let x = 2

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

Desugars à ceci:

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

Si vous regardez la référence de la bibliothèque standard, elle peut vous dire exactement ce que le ~= est surchargé à faire : inclus correspond à la correspondance de plage et à l'équivalent. (Ne correspond pas à la correspondance cas-cas, qui est une fonctionnalité de langage plutôt qu'une fonction dans la bibliothèque std)

Vous verrez que cela ne correspond pas à un booléen droit sur le côté gauche. Pour ce type de comparaison, vous devez ajouter une instruction where.

Sauf si ... vous surchargez vous-même l'opérateur ~=. (Ceci est généralement pas recommandé) Une possibilité serait quelque chose comme ceci:

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

Cela correspond donc à une fonction qui renvoie un booléen de gauche à son paramètre de droite. Voici le genre de chose pour laquelle vous pourriez l'utiliser:

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

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

Pour votre cas, vous pourriez avoir une déclaration qui ressemble à ceci:

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

Mais maintenant, vous devez définir les nouvelles fonctions isNegative et isPositive. À moins de surcharger d'autres opérateurs ...

Vous pouvez surcharger les opérateurs infixes normaux pour qu’ils soient des opérateurs préfixés ou postfixés au curry. Voici un exemple:

postfix operator < {}

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

Cela fonctionnerait comme ceci:

let isGreaterThanFive = 5<

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

Combinez cela avec la fonction précédente, et votre instruction switch peut ressembler à ceci:

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

Maintenant, vous ne devriez probablement pas utiliser ce genre de chose dans la pratique: c'est un peu risqué. Vous ferez (probablement) mieux de vous en tenir à la déclaration where. Cela dit, le modèle de déclaration de commutateur de

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

ou

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

Cela semble assez commun pour que cela mérite d'être considéré.

19
oisdk

Vous pouvez:

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

Puisque quelqu'un a déjà posté case let x where x < 0:, voici une alternative pour où someVar est un Int.

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

Et voici une alternative pour où someVar est un Double:

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

Voici à quoi ça ressemble avec les gammes

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

L'expression <0 ne fonctionne pas (plus?) Alors je me suis retrouvé avec ceci:

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

Heureux que Swift 4 résolve le problème: En guise d'une solution de contournement dans 3, j'ai:

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

Fonctionne mais pas idéal

2
Jeremy Andrews