Znam switchinstrukcje 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 switchinstrukcje 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 someVarjest to Intlub inny Comparable, możesz opcjonalnie przypisać operand do nowej zmiennej. Dzięki temu możesz określić zakres, jak chcesz, używając wheresł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ż wherecał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.
assertionFailurewydaje 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.
PartialRangeFromiPartialRangeUpTolet value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
ClosedRangeiRangelet 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()
}
RangeExpressionprotokołu~=(_:_:)let value = 1
switch true {
case 1... ~= value:
print("greater than zero")
case ..<0 ~= value:
print("less than zero")
default:
print("zero")
}
Equatableprotokoł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, PartialRangeUpToa RangeExpressionjest 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.1zgłasza błąd krytyczny, ponieważ 1...obejmuje tylko liczby od 1. Więc to rozwiązanie działa tylko wtedy, gdy valuejest, Intale jest to niebezpieczne, ponieważ jeśli typ zmiennej zostanie zmieniony, funkcjonalność zostanie przerwana bez żadnego błędu kompilatora.
switchOś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 isNegativei isPositivefunkcje. 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 wherestwierdzenia. 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 someVarjest Int.
switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}
A oto alternatywa dla gdzie someVarjest 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"
}
<0Wyraż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_MAXzostała zastąpiona .greatestFiniteMagnitude, tj Double.greatestFiniteMagnitude, CGFloat.greatestFiniteMagnitudeitd. Więc zwykle, można po prostu zrobić case 0..< .greatestFiniteMagnitudeod rodzaju someVarjest 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)
someVarbył Inti 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