[英]How can I define custom operators to deal with Range of String.Index in Swift?
I find using String.Index
really needs a lot of code in Swift, especially when it comes to methods of Range
Swift doesn't have.我发现在 Swift 中使用
String.Index
确实需要很多代码,尤其是涉及到Range
Swift 没有的方法时。 Like in above code where I don't want an open range (both bounds exclusive).就像上面的代码一样,我不想要一个开放的范围(两个边界都不包括)。 So I wonder if I can extend
String
or Range
or something to simplify it.所以我想知道我是否可以扩展
String
或Range
或其他东西来简化它。 In the following code, I already know that startIndex
and endIndex
are of type String.Index
, and startIndex..<endIndex
is of type Range<String.Index>
.在下面的代码中,我已经知道
startIndex
和endIndex
是String.Index
类型,而startIndex..<endIndex
是Range<String.Index>
类型。 But when I extend String.Index
, I'd like to define a method like static func >.< (lhs: String.Index, rhs: String.Index) -> Range<String.Index>
, but I failed because there's no method to step String.Index
up or down.但是当我扩展
String.Index
时,我想定义一个像static func >.< (lhs: String.Index, rhs: String.Index) -> Range<String.Index>
这样的方法,但我失败了,因为没有向上或向下步进String.Index
的方法。
let startIndex = str.index(str.firstIndex(of: "[") ?? str.startIndex, offsetBy: 1)
let endIndex = str.firstIndex(of: "]") ?? str.startIndex
let subStr = str[startIndex..<endIndex]
I want to define operators like below.我想像下面这样定义运算符。 To clarify them using interval notation , if native method
a...b
is equivalent to [a, b] and a..<b
is equivalent to [a, b), what is the equivalent of (a, b) and (a,b].为了使用区间符号来阐明它们,如果本机方法
a...b
等同于 [a, b] 并且a..<b
等同于 [a, b],那么 (a, b) 和 ( a,b]。
let startIndex = str.firstIndex(of: "[") ?? str.startIndex
let endIndex = str.firstIndex(of: "]") ?? str.startIndex
let subStr1 = str[startIndex...endIndex] // [a, b]
let subStr3 = str[startIndex..<endIndex] // [a, b)
let subStr2 = str[startIndex>.<endIndex] // (a, b)
let subStr4 = str[startIndex>..endIndex] // (a, b]
Edit: See the second code example instead;编辑:请参阅第二个代码示例; Please disregard the first block, I didn't read the question as carefully as I should have.
请忽略第一块,我没有像我应该的那样仔细阅读问题。 so it is not a relevant solution.
所以这不是一个相关的解决方案。
Edit 2: Also look at the first comment below this answer for an example of a major caveat of the first example.编辑 2:另请查看此答案下方的第一条评论,以获取第一个示例的主要警告示例。 It does not work correctly for strings which contain emojis.
对于包含表情符号的字符串,它无法正常工作。 Credit to Leo Dabus for this discovery.
这一发现归功于 Leo Dabus。
This code might do what you're looking for, but I can't guarantee its reliability in all cases.这段代码可能会满足您的要求,但我不能保证它在所有情况下的可靠性。
What it does is take a regular half-open range of integers (of the form a..<b
) and a specific string (because, as matt mentioned in his comment, Swift string indices don't pertain to the class String
, only to some particular string), and returns an open range of indices for that particular string.它所做的是采用常规的半开整数范围(形式
a..<b
)和特定字符串(因为,正如马特在他的评论中提到的那样, Swift 字符串索引不属于 class String
,仅到某个特定的字符串),并返回该特定字符串的开放索引范围。
In effect, it just adds 1 to the lower bound to change it from inclusive to exclusive.实际上,它只是将下限加 1 以将其从包含更改为排除。
import Foundation
// Returns a Range of 'String.Index'es where both upper and lower bounds are exclusive.
extension Range {
// Here, the upper bound of the range was already exclusive, so don't subtract 1 from it. Only add 1 to the lower bound.
static func OpenRange(string: String, range: Range<Int>) -> Range<String.Index> {
return Range<String.Index>(uncheckedBounds: (String.Index(utf16Offset: range.lowerBound + 1, in: string), String.Index(utf16Offset: range.upperBound, in: string)))
}
}
let theString = "abcdefg"
let endIndex = theString.index(theString.startIndex, offsetBy: 5)
let range: Range<String.Index> = theString.startIndex..<endIndex
let openRange = Range<String.Index>.OpenRange(string: theString, range: 0..<5)
print(theString[range]) // prints 'abcde'
print(theString[openRange]) // prints 'bcde'
Reference: https://www.avanderlee.com/swift/ranges-explained/参考资料: https://www.avanderlee.com/swift/ranges-explained/
The example I had above doesn't really fit the specific case you were asking about though, as I was starting from code I already had and was trying to 'adapt' it to this situation.我上面的例子并不真正适合你问的具体情况,因为我是从我已经拥有的代码开始的,并试图“适应”它以适应这种情况。 My bad: I believe this is a better alternative:
我的坏处:我相信这是一个更好的选择:
// Returns a Range of 'String.Index'es between two specified characters in the string (as exclusive bounds)
extension Range {
// Here, the upper bound of the range was already exclusive, so don't subtract 1 from it. Only add 1 to the lower bound.
static func OpenRange(string: String, from: String, to: String) -> Range<String.Index> {
// The 'firstIndex' method expects a Character, not a String, so you need a type cast here
let lowerInclusive = string.firstIndex(of: Character(from))!
let lowerExclusive = string.index(lowerInclusive, offsetBy: 1)
let upperExclusive = string.firstIndex(of: Character(to))!
return Range<String.Index>(uncheckedBounds: (lowerExclusive, upperExclusive))
}
}
let theString = "[10:02.11]"
let openRange1 = Range<String.Index>.OpenRange(string: theString, from: "[", to: ":")
let openRange2 = Range<String.Index>.OpenRange(string: theString, from: ":", to: "]")
print(theString[openRange1]) // prints '10'
print(theString[openRange2]) // prints '02.11'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.