比较String.Index值
是否可以比较Swift中的两个比较String.Index值,string,macos,swift,String,Macos,Swift,是否可以比较Swift中的两个String.Index值?我试图一个字符一个字符地处理一个字符串,有几次我需要检查我是否在字符串的末尾。我已经试过了 while (currentIndex < string.endIndex) { //do things... currentIndex = currentIndex.successor() } while(currentIndex
String.Index
值?我试图一个字符一个字符地处理一个字符串,有几次我需要检查我是否在字符串的末尾。我已经试过了
while (currentIndex < string.endIndex) {
//do things...
currentIndex = currentIndex.successor()
}
while(currentIndex
它抱怨类型转换。然后,我尝试定义并重载
字符串索引支持=
和=代码>。字符串索引是不透明类型,不是整数,不能与整数进行比较
使用:if(currentIndex!=string.endIndex)
最简单的选项是distance()
函数:
var string = "Hello World"
var currentIndex = string.startIndex
while (distance(currentIndex, string.endIndex) >= 0) {
println("currentIndex: \(currentIndex)")
currentIndex = currentIndex.successor()
}
注意distance()
具有O(N)
性能,因此避免使用大型字符串。但是,整个String类目前并不处理大字符串——如果性能非常关键,您可能应该切换到CFString
使用运算符重载是一个坏主意,但作为一个学习练习,您应该这样做:
var string = "Hello World"
var currentIndex = string.startIndex
@infix func <(lhs: String.Index, rhs: String.Index) -> Bool {
return distance(lhs, rhs) > 0
}
while (currentIndex < string.endIndex) {
currentIndex = currentIndex.successor()
}
var string=“你好,世界”
var currentIndex=string.startIndex
@中缀函数布尔{
返回距离(左、右)大于0
}
while(currentIndex
我相信这个REPL/PLAYOND示例应该说明您(和其他人)需要了解的有关使用String.Index概念的知识
// This will be our working example
let exampleString = "this is a string"
// And here we'll call successor a few times to get an index partway through the example
var someIndexInTheMiddle = exampleString.startIndex
for _ in 1...5 {
someIndexInTheMiddle = someIndexInTheMiddle.successor()
}
// And here we will iterate that string and detect when our current index is relative in one of three different possible ways to the character selected previously
println("\n\nsomeIndexInTheMiddle = \(exampleString[someIndexInTheMiddle])")
for var index: String.Index = exampleString.startIndex; index != exampleString.endIndex; index = index.successor() {
println(" - \(exampleString[index])")
if index != exampleString.startIndex && index.predecessor() == someIndexInTheMiddle {
println("current character comes after someIndexInTheMiddle")
} else if index == someIndexInTheMiddle {
println("current character is the one indicated by someIndexInTheMiddle")
} else if index != exampleString.endIndex && index.successor() == someIndexInTheMiddle {
println("Current character comes before someIndexinTheMiddle")
}
}
希望这能提供必要的信息。无论您决定以何种方式对字符串进行迭代,您都会立即希望在一个函数中捕获迭代,该函数可以在对每个字符串应用闭包时重复调用。例如:
extension String {
func each (f: (Character) -> Void) {
for var index = self.startIndex;
index < self.endIndex;
index = index.successor() {
f (string[index])
}
}
}
扩展字符串{
func每个(f:(字符)->Void){
对于var指数=self.startIndex;
指数
苹果已经为C字串提供了这些功能,一旦字符访问固化,苹果将为普通字串提供这些功能。覆盖运算符不是解决方案。显然,在Swift 3中覆盖,似乎我意识到这是正确的答案,但作为一个附带问题,有什么方法可以检查一个索引是在另一个索引之前还是之后?如果这样做,您将错过最后一个索引。如果调用currentIndex.succession
,则只能错过最后一个字符。但请提交一份bug报告,这是测试版。还要注意的是,在第4节中有一个很大的变化,所以很有可能会有改进。整个unicode问题仍然有很多问题,但是苹果和Swift解决了很多问题。是的,字符串肯定有一些限制。唯一一个需要执行复杂字符串操作的项目是我坚持使用CFString。我怀疑我正在利用的一些更高级的东西永远不可能使用字符串。使用CFString
的问题是,它不会处理表情符号,代理项对不是组合的,比如标志字符,它们都不能在UTF-16unichar
中表示。这就是我要寻找的O(n)
性能有点烦人,尽管可能不会对我正在使用的字符串造成任何问题。为什么你会说使用操作符重载是个坏主意?@Jumhyn注意字符串类当前充满了O(n)
性能问题。不管怎样,你都会遇到他们。这似乎是课堂上的一个普遍设计缺陷。毫无疑问,他们总有一天会修复它,但现在我们只需要接受它——或者使用NS/CFString。稍后,当其他人正在编写代码时,他们将不理解其用法。再加上大量的开发人员使各种事情超载,这将导致灾难。最好的解决方案是最清晰的解决方案,这一解决方案稍后将导致每分钟WTF数减少。@AbhiBeckert但是CFString
和NSString
在处理表情符号、代理项对和组合(如标记字符)时都存在重大问题,这些都无法在UTF-16 unichar中表示。尤其是表情符号的出现频率越来越高。String.utf16为您提供了另一种表示方式,它更接近NSString和CFString索引的工作方式。您可以使用整数索引并对索引进行计算,但目前,它缺少查找和匹配字符串的函数,因此您必须自己实现这些函数。它还受到NSString和CFString的所有缺点的影响。
// This will be our working example
let exampleString = "this is a string"
// And here we'll call successor a few times to get an index partway through the example
var someIndexInTheMiddle = exampleString.startIndex
for _ in 1...5 {
someIndexInTheMiddle = someIndexInTheMiddle.successor()
}
// And here we will iterate that string and detect when our current index is relative in one of three different possible ways to the character selected previously
println("\n\nsomeIndexInTheMiddle = \(exampleString[someIndexInTheMiddle])")
for var index: String.Index = exampleString.startIndex; index != exampleString.endIndex; index = index.successor() {
println(" - \(exampleString[index])")
if index != exampleString.startIndex && index.predecessor() == someIndexInTheMiddle {
println("current character comes after someIndexInTheMiddle")
} else if index == someIndexInTheMiddle {
println("current character is the one indicated by someIndexInTheMiddle")
} else if index != exampleString.endIndex && index.successor() == someIndexInTheMiddle {
println("Current character comes before someIndexinTheMiddle")
}
}
extension String {
func each (f: (Character) -> Void) {
for var index = self.startIndex;
index < self.endIndex;
index = index.successor() {
f (string[index])
}
}
}