问题
let smallRange = 1..<2
let largeRange = 0..<10
largeRange ~= smallRange // False
Why does this compile at the first place!?
But if it compiles the answer should be True
The next code works:
smallRange.clamped(to: largeRange) == smallRange // True
Is there any simpler way to check?
回答1:
I don't think you will find a "simpler" or "shorter" way of writing this but you can define your own pattern matching operator to shorten your code:
extension Range {
static func ~=(lhs: Self, rhs: Self) -> Bool {
rhs.clamped(to: lhs) == rhs
}
}
extension ClosedRange {
static func ~=(lhs: Self, rhs: Self) -> Bool {
rhs.clamped(to: lhs) == rhs
}
}
let smallRange = 1..<2
let largeRange = 0..<10
smallRange ~= largeRange // false
largeRange ~= smallRange // true
Note: It compiles because there is a generic implementation used to check for equality like switching a string therefore it would only return true if both ranges were the same.
func ~= <T>(a: T, b: T) -> Bool where T : Equatable
回答2:
You seem to have a working formula. So why not just use it? Problem solved. If, however, you think your working formula is too long, hard to remember, whatever, then simply refactor it into an extension so you can shorten it:
extension Range {
func embraces(_ other: Self) -> Bool {
return other.clamped(to: self) == other
}
}
Now you can say
largeRange.embraces(smallRange) // true
That's shorter. Simpler. Whatever.
That's (part of) what programming is. If you don't like the language, change it.
回答3:
You can compare the lowerBound
and upperBound
of the 2 ranges (or use the contains
function to check that one range contains both bounds of the other range) to learn if one is a subset of the other.
extension Range {
func contains(otherRange: Range) -> Bool {
lowerBound <= otherRange.lowerBound && upperBound >= otherRange.upperBound
}
}
let smallRange = 1..<2
let middleRange = 5..<8
let largeRange = 0..<10
smallRange.contains(otherRange: middleRange) // false
middleRange.contains(otherRange: smallRange) // false
largeRange.contains(otherRange: middleRange) // true
The other solution using contains
:
extension Range {
func contains(otherRange: Range) -> Bool {
contains(otherRange.lowerBound) && contains(otherRange.upperBound)
}
}
回答4:
Well, if one range is between another, it means that the edges are between each other
So, in your example, it would be largeRange.first < smallRange.first && largeRange.last > smallRange.last
来源:https://stackoverflow.com/questions/64066681/check-if-one-range-is-within-another