Tôi quen thuộc với các switch
câu lệnh trong Swift, nhưng tự hỏi làm thế nào để thay thế đoạn mã này bằng switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Tôi quen thuộc với các switch
câu lệnh trong Swift, nhưng tự hỏi làm thế nào để thay thế đoạn mã này bằng switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Câu trả lời:
Đây là một cách tiếp cận. Giả sử someVar
là một Int
hoặc khác Comparable
, bạn có thể tùy ý gán toán hạng cho một biến mới. Điều này cho phép bạn phạm vi nó theo cách bạn muốn bằng cách sử dụng where
từ khóa:
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")
}
Điều này có thể được đơn giản hóa một chút:
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")
}
Bạn cũng có thể tránh where
hoàn toàn từ khóa với phạm vi phù hợp:
switch someVar {
case Int.min..<0:
print("someVar is \(someVar)")
case 0:
print("someVar is 0")
default:
print("someVar is \(someVar)")
}
default: fatalError()
phát hiện sớm các lỗi logic có thể xảy ra.
assertionFailure
dường như là một lựa chọn an toàn hơn, đặc biệt là khi làm việc trong nhóm.
Với Swift 5, bạn có thể chọn một trong các công tắc sau để thay thế câu lệnh if của mình.
PartialRangeFrom
vàPartialRangeUpTo
let value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
ClosedRange
và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()
}
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
giao thức~=(_:_:)
let value = 1
switch true {
case 1... ~= value:
print("greater than zero")
case ..<0 ~= value:
print("less than zero")
default:
print("zero")
}
Equatable
giao thức~=(_:_:)
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
và RangeExpression
's contains(_:)
phương pháplet 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
ném một lỗi nghiêm trọng vì 1...
chỉ bao gồm các số từ 1. Vì vậy, giải pháp này chỉ hoạt động nếu value
là một Int
nhưng điều đó là nguy hiểm vì nếu loại biến thay đổi chức năng bị phá vỡ mà không có lỗi biên dịch.
Câu switch
lệnh, dưới mui xe, sử dụng ~=
toán tử. Vậy đây:
let x = 2
switch x {
case 1: print(1)
case 2: print(2)
case 3..<5: print(3..<5)
default: break
}
Desugars cho điều này:
if 1 ~= x { print(1) }
else if 2 ~= x { print(2) }
else if 3..<5 ~= x { print(3..<5) }
else { }
Nếu bạn nhìn vào tài liệu tham khảo thư viện tiêu chuẩn, nó có thể cho bạn biết chính xác những gì ~=
bị quá tải để làm : bao gồm là khớp phạm vi và đánh đồng cho những thứ tương đương. (Không bao gồm khớp enum-case, là một tính năng ngôn ngữ, chứ không phải là một chức năng trong lib std)
Bạn sẽ thấy rằng nó không khớp với một boolean thẳng ở phía bên trái. Đối với những loại so sánh đó, bạn cần thêm một câu lệnh where.
Trừ khi ... bạn tự làm quá tải người ~=
vận hành. (Điều này thường không được khuyến nghị) Một khả năng sẽ là như thế này:
func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
return lhs(rhs)
}
Vì vậy, nó phù hợp với một hàm trả về một boolean ở bên trái với tham số của nó ở bên phải. Đây là loại điều bạn có thể sử dụng nó cho:
func isEven(n: Int) -> Bool { return n % 2 == 0 }
switch 2 {
case isEven: print("Even!")
default: print("Odd!")
}
Đối với trường hợp của bạn, bạn có thể có một tuyên bố như thế này:
switch someVar {
case isNegative: ...
case 0: ...
case isPositive: ...
}
Nhưng bây giờ bạn phải xác định mới isNegative
vàisPositive
chức năng. Trừ khi bạn quá tải một số toán tử ...
Bạn có thể quá tải các toán tử infix bình thường để trở thành các toán tử tiền tố hoặc hậu tố. Đây là một ví dụ:
postfix operator < {}
postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
return lhs < rhs
}
Điều này sẽ làm việc như thế này:
let isGreaterThanFive = 5<
isGreaterThanFive(6) // true
isGreaterThanFive(5) // false
Kết hợp điều đó với chức năng trước đó và câu lệnh chuyển đổi của bạn có thể trông như thế này:
switch someVar {
case 0< : print("Bigger than 0")
case 0 : print("0")
default : print("Less than 0")
}
Bây giờ, có lẽ bạn không nên sử dụng loại điều này trong thực tế: đó là một chút tinh ranh. Bạn (có lẽ) tốt hơn hết là gắn bó với where
tuyên bố. Điều đó nói rằng, mẫu câu lệnh chuyển đổi của
switch x {
case negative:
case 0:
case positive:
}
hoặc là
switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}
Có vẻ đủ phổ biến cho nó là đáng để xem xét.
Vì ai đó đã đăng case let x where x < 0:
ở đây là một thay thế cho nơi someVar
là một Int
.
switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}
Và đây là một thay thế cho someVar
một Double
:
case -(Double.infinity)...0: // do something
// etc
Đây là cách nó trông giống như với phạm vi
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"
}
Các <0
biểu hiện không làm việc (nữa?) Vì vậy tôi đã kết thúc với điều này:
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
đã được thay thế bởi .greatestFiniteMagnitude
, tức là Double.greatestFiniteMagnitude
, CGFloat.greatestFiniteMagnitude
v.v. Thông thường, bạn chỉ có thể thực hiện case 0..< .greatestFiniteMagnitude
vì loại someVar
đã được biết đến
var timeLeft = 100
switch timeLeft {case 0...<=7200: print("ok") default:print("nothing") }
Tại sao <=
nhà điều hành không được công nhận? Nếu tôi viết nó mà không bằng nó hoạt động. Cảm ơn
case 0...7200:
Toán tử <=
là toán tử so sánh. Trong một chuyển đổi, bạn chỉ có thể sử dụng các toán tử phạm vi (xem tài liệu)
someVar
là một Int
và tôi phải thực hiện một Double(
sốVar) `để làm cho nó hoạt động ...
Rất vui khi Swift 4 giải quyết vấn đề:
Như một cách giải quyết trong 3 tôi đã làm:
switch translation.x {
case 0..<200:
print(translation.x, slideLimit)
case -200..<0:
print(translation.x, slideLimit)
default:
break
}
Hoạt động nhưng không lý tưởng