繁体   English   中英

枚举快速字符串时获取“ String.Index”

[英]Getting “String.Index” while enumerating swift string

目前,我们迭代字符串如下:

let greeting = "Hello"
for (intIndex, char) in greeting.enumerated() {
    let currentIndex = greeting.index(greeting.startIndex, offsetBy: intIndex)
    let indexAfterCurrentIndex = greeting.index(after: currentIndex)
    print(greeting[indexAfterCurrentIndex...])
}

我觉得用下面的代码写是多余的。

let currentIndex = greeting.index(greeting.startIndex, offsetBy: intIndex)

还有其他方法可以在迭代时直接获取“ String.Index”吗?

像这样

let greeting = "Hello"
for (stringIndex, char) in greeting.enumeratedXXX() {
    let indexAfterCurrentIndex = greeting.index(after: stringIndex)
    print(greeting[indexAfterCurrentIndex...])
}

没有内置功能。 您可以将其包装在一个自定义的迭代器中,但是然后您只能将相同类型的计算封装在不同的位置,所以这不是一个答案:)

代码复杂度

但是,您可以提高当前代码的性能:

greeting.index(greeting.startIndex, offsetBy: intIndex)
  • 这将为每次循环迭代计算从startIndex到结果索引的索引。
  • 使用index(_:offsetBy:)的索引计算实际上只是另一个循环本身,其中每个索引+1 没有O(1)方式可以“计算”索引; 通过O(n)的循环找到它

因此,您自己的外部循环与O(n)成线性关系,共进行n次迭代,每个字符一个。

然后使用内部循环计算索引意味着有1+2+3+4+5+6+...n = (n^2 + n)/2次迭代,其中nintIndex

这意味着该算法具有*免除*回旋的复杂度O(n + n^2) 二次部分是有问题的!

更好的方法

您可以将复杂度降低到每个迭代2个操作,即O(2n) 只需将先前计算的索引保留在内存中,然后自己+1,就可以避免重新编写代码。

这是代码:

let greeting = "Hello"
var index = greeting.startIndex
for char in greeting {
    let indexAfterCurrentIndex = greeting.index(after: index)
    print(greeting[indexAfterCurrentIndex...])
    index = indexAfterCurrentIndex
}

仍然不是一个简单的内置解决方案,但是您可以包装这种更有效的算法,然后就可以使用!

extension String {
    func forEachCharacterWithIndex(iterator: (String.Index, Character) -> Void) {
        var currIndex = self.startIndex
        for char in self {
            iterator(currIndex, char)
            currIndex = self.index(after: currIndex)
        }
    }
}

let greeting = "Hello"
greeting.forEachCharacterWithIndex { (index, char) in
    let indexAfterCurrentIndex = greeting.index(after: index)
    print(greeting[indexAfterCurrentIndex...])
}

如果需要字符串索引,则可以枚举greeting.indices

let greeting = "Hello"
for index in greeting.indices {
    // ...
}

如果需要每个字符及其索引,则可以并行枚举字符串和索引:

let greeting = "Hello"
for (char, currentIndex) in zip(greeting, greeting.indices) {
    let indexAfterCurrentIndex = greeting.index(after: currentIndex)
    print(char, "-", greeting[indexAfterCurrentIndex...])
}

输出:

H - ello
e - llo
l - lo
l - o
o -

一个更简单的变体是

let greeting = "Hello"
for (char, nextIndex) in zip(greeting, greeting.indices.dropFirst()) {
    print(char, "-", greeting[nextIndex...])
}

仅在没有最后一个字符/索引对的情况下产生几乎相同的结果:

H - ello
e - llo
l - lo
l - o

为什么不将currentIndex增加1?

let greeting = "Hello"
for (stringIndex, char) in greeting.enumerated() {
    let currentIndex = stringIndex
    let nextIndex = currentIndex + 1
    print(nextIndex)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM