Znam switch
instrukcje w Swift, ale zastanawiam się, jak zamienić ten fragment kodu na switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Znam switch
instrukcje w Swift, ale zastanawiam się, jak zamienić ten fragment kodu na switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Odpowiedzi:
Oto jedno podejście. Zakładając, że someVar
jest to Int
lub inny Comparable
, możesz opcjonalnie przypisać operand do nowej zmiennej. Dzięki temu możesz określić zakres, jak chcesz, używając where
słowa kluczowego:
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")
}
Można to nieco uprościć:
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")
}
Możesz również where
całkowicie uniknąć słowa kluczowego dzięki dopasowaniu zakresu:
switch someVar {
case Int.min..<0:
print("someVar is \(someVar)")
case 0:
print("someVar is 0")
default:
print("someVar is \(someVar)")
}
default: fatalError()
wczesne wykrywanie możliwych błędów logicznych.
assertionFailure
wydaje się być bezpieczniejszą opcją, szczególnie podczas pracy w zespole.
Dzięki Swift 5 możesz wybrać jeden z poniższych przełączników, aby zastąpić instrukcję if.
PartialRangeFrom
iPartialRangeUpTo
let value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
ClosedRange
iRange
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
protokołu~=(_:_:)
let value = 1
switch true {
case 1... ~= value:
print("greater than zero")
case ..<0 ~= value:
print("less than zero")
default:
print("zero")
}
Equatable
protokołu~=(_:_:)
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()
}
PartialRangeFrom
, PartialRangeUpTo
a RangeExpression
jest contains(_:)
metodalet 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
zgłasza błąd krytyczny, ponieważ 1...
obejmuje tylko liczby od 1. Więc to rozwiązanie działa tylko wtedy, gdy value
jest, Int
ale jest to niebezpieczne, ponieważ jeśli typ zmiennej zostanie zmieniony, funkcjonalność zostanie przerwana bez żadnego błędu kompilatora.
switch
Oświadczenie, pod maską, używa ~=
operatora. Więc to:
let x = 2
switch x {
case 1: print(1)
case 2: print(2)
case 3..<5: print(3..<5)
default: break
}
Cukry do tego:
if 1 ~= x { print(1) }
else if 2 ~= x { print(2) }
else if 3..<5 ~= x { print(3..<5) }
else { }
Jeśli spojrzysz na odniesienie do biblioteki standardowej, może ci dokładnie powiedzieć, do czego ~=
jest przeciążona : dołączone jest dopasowywanie zakresu i zrównanie dla równych rzeczy. (Nie uwzględniono dopasowania wyliczenia wielkości liter, co jest funkcją języka, a nie funkcją w standardowej bibliotece)
Zobaczysz, że nie pasuje do prostej wartości logicznej po lewej stronie. W przypadku tego rodzaju porównań należy dodać instrukcję gdzie.
Chyba że ... sam przeciążasz ~=
operatora. (Generalnie nie jest to zalecane) Jedną z możliwości byłoby coś takiego:
func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
return lhs(rhs)
}
Więc to dopasowuje funkcję, która zwraca wartość logiczną po lewej stronie do parametru po prawej stronie. Oto rodzaj rzeczy, do których możesz go użyć:
func isEven(n: Int) -> Bool { return n % 2 == 0 }
switch 2 {
case isEven: print("Even!")
default: print("Odd!")
}
W twoim przypadku możesz mieć oświadczenie, które wygląda następująco:
switch someVar {
case isNegative: ...
case 0: ...
case isPositive: ...
}
Ale teraz musisz zdefiniować nowe isNegative
i isPositive
funkcje. Chyba że przeładujesz więcej operatorów ...
Możesz przeciążać zwykłe operatory wrostkowe, aby były one operatorami prefiksowymi lub postfiksowymi. Oto przykład:
postfix operator < {}
postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
return lhs < rhs
}
To działałoby tak:
let isGreaterThanFive = 5<
isGreaterThanFive(6) // true
isGreaterThanFive(5) // false
Połącz to z wcześniejszą funkcją, a instrukcja switch może wyglądać następująco:
switch someVar {
case 0< : print("Bigger than 0")
case 0 : print("0")
default : print("Less than 0")
}
Prawdopodobnie nie powinieneś używać tego typu rzeczy w praktyce: jest to trochę podejrzane. (Prawdopodobnie) lepiej trzymać się tego where
stwierdzenia. To powiedziawszy, wzorzec instrukcji przełącznika
switch x {
case negative:
case 0:
case positive:
}
lub
switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}
Wydaje się na tyle powszechne, że warto się nad tym zastanowić.
Ponieważ ktoś już opublikował case let x where x < 0:
tutaj, jest alternatywą dla gdzie someVar
jest Int
.
switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}
A oto alternatywa dla gdzie someVar
jest Double
:
case -(Double.infinity)...0: // do something
// etc
Tak to wygląda z zakresami
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"
}
<0
Wyrażenie nie działa (już?), Więc skończyło się w ten sposób:
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
została zastąpiona .greatestFiniteMagnitude
, tj Double.greatestFiniteMagnitude
, CGFloat.greatestFiniteMagnitude
itd. Więc zwykle, można po prostu zrobić case 0..< .greatestFiniteMagnitude
od rodzaju someVar
jest już znany
var timeLeft = 100
switch timeLeft {case 0...<=7200: print("ok") default:print("nothing") }
Dlaczego <=
operator nie jest rozpoznawany? Jeśli napiszę to bez równości, to działa. Dzięki
case 0...7200:
Operator <=
jest operatorem porównania. W przełączniku możesz używać tylko operatorów zasięgu (patrz dokumentacja)
someVar
był Int
i musiałem zrobić Double(
someVar) `, aby działał ...
Cieszę się, że Swift 4 rozwiązuje problem:
Jako obejście w 3 zrobiłem:
switch translation.x {
case 0..<200:
print(translation.x, slideLimit)
case -200..<0:
print(translation.x, slideLimit)
default:
break
}
Działa, ale nie jest idealny