Ho familiarità con le switch
dichiarazioni in Swift, ma mi chiedo come sostituire questo pezzo di codice con un switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Ho familiarità con le switch
dichiarazioni in Swift, ma mi chiedo come sostituire questo pezzo di codice con un switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Risposte:
Ecco un approccio. Supponendo che someVar
sia uno Int
o l'altro Comparable
, è possibile assegnare facoltativamente l'operando a una nuova variabile. Questo ti permette di mirare come vuoi usando la where
parola chiave:
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")
}
Questo può essere semplificato un po ':
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")
}
Puoi anche evitare la where
parola chiave interamente con la corrispondenza dell'intervallo:
switch someVar {
case Int.min..<0:
print("someVar is \(someVar)")
case 0:
print("someVar is 0")
default:
print("someVar is \(someVar)")
}
default: fatalError()
di rilevare presto possibili errori logici.
assertionFailure
sembra essere un'opzione più sicura, specialmente quando si lavora in gruppo.
Con Swift 5, puoi scegliere una delle seguenti opzioni per sostituire la tua dichiarazione if.
PartialRangeFrom
ePartialRangeUpTo
let value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
ClosedRange
eRange
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' ~=(_:_:)
operatore del protocollolet value = 1
switch true {
case 1... ~= value:
print("greater than zero")
case ..<0 ~= value:
print("less than zero")
default:
print("zero")
}
Equatable
l' ~=(_:_:)
operatore del protocollolet 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
e RangeExpression
il contains(_:)
metodolet 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
genera un errore fatale perché 1...
copre solo numeri da 1. Quindi questa soluzione funziona solo se value
è un Int
ma che è pericoloso perché se il tipo di variabile cambia la funzionalità si interrompe senza alcun errore del compilatore.
La switch
dichiarazione, sotto il cofano, utilizza l' ~=
operatore. Così questo:
let x = 2
switch x {
case 1: print(1)
case 2: print(2)
case 3..<5: print(3..<5)
default: break
}
Desugars a questo:
if 1 ~= x { print(1) }
else if 2 ~= x { print(2) }
else if 3..<5 ~= x { print(3..<5) }
else { }
Se guardi il riferimento alla libreria standard, può dirti esattamente quale ~=
deve fare il sovraccarico : incluso è il range-matching e equivale a cose equabili. (Non è inclusa la corrispondenza enum case, che è una caratteristica del linguaggio, piuttosto che una funzione nella libreria std)
Vedrai che non corrisponde a un booleano diretto sul lato sinistro. Per questo tipo di confronti, è necessario aggiungere un'istruzione where.
A meno che ... non sovraccarichi l' ~=
operatore da solo. (Questo è generalmente non raccomandata) Una possibilità potrebbe essere qualcosa di simile:
func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
return lhs(rhs)
}
Quindi corrisponde a una funzione che restituisce un valore booleano a sinistra al suo parametro a destra. Ecco il tipo di cosa per cui potresti usarlo:
func isEven(n: Int) -> Bool { return n % 2 == 0 }
switch 2 {
case isEven: print("Even!")
default: print("Odd!")
}
Nel tuo caso, potresti avere un'affermazione simile a questa:
switch someVar {
case isNegative: ...
case 0: ...
case isPositive: ...
}
Ma ora devi definire nuovo isNegative
eisPositive
funzioni. A meno che non sovraccarichi altri operatori ...
È possibile sovraccaricare i normali operatori infix per essere operatori currix o postfix. Ecco un esempio:
postfix operator < {}
postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
return lhs < rhs
}
Funzionerebbe così:
let isGreaterThanFive = 5<
isGreaterThanFive(6) // true
isGreaterThanFive(5) // false
Combinalo con la funzione precedente e la tua istruzione switch può apparire così:
switch someVar {
case 0< : print("Bigger than 0")
case 0 : print("0")
default : print("Less than 0")
}
Ora, probabilmente non dovresti usare questo genere di cose in pratica: è un po 'complicato. Probabilmente stai meglio con la where
dichiarazione. Detto questo, il modello di istruzione switch di
switch x {
case negative:
case 0:
case positive:
}
o
switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}
Sembra abbastanza comune per cui valga la pena considerare.
Dal momento che qualcuno ha già pubblicato case let x where x < 0:
qui è un'alternativa per dove si someVar
trova un Int
.
switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}
Ed ecco un'alternativa per dove someVar
è un Double
:
case -(Double.infinity)...0: // do something
// etc
Ecco come si presenta con le gamme
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
espressione non funziona (più?) Quindi ho finito con questo:
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
è stato sostituito da .greatestFiniteMagnitude
, ad esempio Double.greatestFiniteMagnitude
, CGFloat.greatestFiniteMagnitude
ecc. Quindi di solito, puoi farlo solo case 0..< .greatestFiniteMagnitude
perché il tipo di someVar
è già noto
var timeLeft = 100
switch timeLeft {case 0...<=7200: print("ok") default:print("nothing") }
Perché l' <=
operatore non viene riconosciuto? Se lo scrivo senza eguali funziona. Grazie
case 0...7200:
l'operatore <=
è un operatore di confronto. In uno switch puoi usare solo operatori di range (vedi documenti)
someVar
era un Int
e ho dovuto fare Double(
qualche Var) `per farlo funzionare ...
Sono contento che Swift 4 risolva il problema:
Come soluzione alternativa in 3 ho fatto:
switch translation.x {
case 0..<200:
print(translation.x, slideLimit)
case -200..<0:
print(translation.x, slideLimit)
default:
break
}
Funziona ma non è l'ideale