Je connais les switch
instructions de Swift, mais je me demande comment remplacer ce morceau de code par un switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Je connais les switch
instructions de Swift, mais je me demande comment remplacer ce morceau de code par un switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Réponses:
Voici une approche. En supposant que someVar
c'est un Int
ou un autre Comparable
, vous pouvez éventuellement affecter l'opérande à une nouvelle variable. Cela vous permet de l'étendre comme vous le souhaitez en utilisant le where
mot - clé:
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 un peu simplifié:
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 where
complètement le mot - clé 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)")
}
default: fatalError()
de détecter tôt les éventuelles erreurs de logique.
assertionFailure
semble être une option plus sûre, en particulier lorsque vous travaillez en équipe.
Avec Swift 5, vous pouvez choisir l'un des commutateurs suivants afin de remplacer votre instruction if.
PartialRangeFrom
etPartialRangeUpTo
let value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
ClosedRange
etRange
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()
}
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()
}
_
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()
}
RangeExpression
l' ~=(_:_:)
opérateur du protocolelet value = 1
switch true {
case 1... ~= value:
print("greater than zero")
case ..<0 ~= value:
print("less than zero")
default:
print("zero")
}
Equatable
l' ~=(_:_:)
opérateur du protocolelet 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()
}
PartialRangeFrom
, PartialRangeUpTo
et RangeExpression
de » contains(_:)
méthodelet value = 1
switch true {
case (1...).contains(value):
print("greater than zero")
case (..<0).contains(value):
print("less than zero")
default:
print("zero")
}
0.1
renvoie une erreur fatale car 1...
ne couvre que les nombres à partir de 1. Cette solution ne fonctionne donc que si value
c'est un Int
mais c'est dangereux car si le type de variable change, la fonctionnalité est interrompue sans aucune erreur du compilateur.
La switch
déclaration, 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 bibliothèque standard, elle peut vous dire exactement ce que le ~=
est surchargé à faire : inclus est la correspondance de plage, et l'équation pour des choses égales. (La correspondance enum-case n'est pas incluse, qui est une fonctionnalité de langage, plutôt qu'une fonction dans la bibliothèque std)
Vous verrez qu'il ne correspond pas à un booléen droit sur le côté gauche. Pour ce genre de comparaisons, vous devez ajouter une instruction where.
Sauf si ... vous surchargez l' ~=
opérateur vous-même. (Ce n'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 à gauche à son paramètre à droite. Voici le genre de chose pour laquelle vous pouvez 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 de nouveaux isNegative
etisPositive
fonctions. Sauf si vous surchargez plus d'opérateurs ...
Vous pouvez surcharger les opérateurs d'infixe normaux pour qu'ils soient des opérateurs de préfixe curry ou de suffixe. 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 douteux. Vous feriez (probablement) mieux de vous en tenir à la where
déclaration. Cela dit, le modèle d'instruction switch de
switch x {
case negative:
case 0:
case positive:
}
ou
switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}
Cela semble assez courant pour que cela vaille la peine d'être considéré.
Puisque quelqu'un a déjà posté case let x where x < 0:
ici, c'est une alternative pour où someVar
est un fichier 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
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"
}
L' <0
expression ne fonctionne pas (plus?) Alors j'ai fini 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
}
X_MAX
a été remplacé par .greatestFiniteMagnitude
, c'est-à-dire Double.greatestFiniteMagnitude
, CGFloat.greatestFiniteMagnitude
etc. Donc, généralement, vous pouvez le faire case 0..< .greatestFiniteMagnitude
puisque le type de someVar
est déjà connu
var timeLeft = 100
switch timeLeft {case 0...<=7200: print("ok") default:print("nothing") }
Pourquoi l' <=
opérateur n'est-il pas reconnu? Si je l'écris sans égal, cela fonctionne. Merci
case 0...7200:
L'opérateur <=
est un opérateur de comparaison. Dans un commutateur, vous ne pouvez utiliser que des opérateurs de plage (voir la documentation)
someVar
un Int
et je devais faire Double(
someVar) `pour le faire fonctionner ...
Heureux que Swift 4 résout le problème:
Comme solution de contournement dans 3, j'ai fait:
switch translation.x {
case 0..<200:
print(translation.x, slideLimit)
case -200..<0:
print(translation.x, slideLimit)
default:
break
}
Fonctionne mais pas idéal