0

Currently we iterate string as below:

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...])
}

I feel writing below code is redundant.

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

Is there other way to get directly "String.Index" while iterating?

Something like this

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

3 回答 3

2

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

代码复杂度

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

greeting.index(greeting.startIndex, offsetBy: intIndex)
  • 这将为startIndex每次循环迭代计算从索引到结果索引的索引。
  • 索引计算index(_:offsetBy:)实际上只是另一个循环本身,它+1是每个索引。没有O(1)办法“计算”索引;它是由一个循环发现的O(n)

因此,您自己的外部循环与O(n)forn迭代是线性的,每个字符一个。

然后用内部循环计算索引意味着有1+2+3+4+5+6+...n = (n^2 + n)/2迭代,在这种情况下nintIndex

这意味着该算法具有 *handwaiving* roundabout 的复杂性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...])
}
于 2019-06-20T13:57:03.493 回答
1

如果您需要字符串索引,那么您可以枚举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...])
}

输出:

你好
e-llo
我 - 洛
l - o
o-

一个更简单的变体是

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

它产生几乎相同的结果,只是没有最后一个字符/索引对:

你好
e-llo
我 - 洛
l - o
于 2019-06-20T14:15:35.687 回答
-1

为什么不将 currentIndex 增加 1 ?

let greeting = "Hello"
for (stringIndex, char) in greeting.enumerated() {
    let currentIndex = stringIndex
    let nextIndex = currentIndex + 1
    print(nextIndex)
}
于 2019-06-20T13:55:52.163 回答