【问题标题】:Swift Type 'string.index' has no subscript membersSwift Type 'string.index' 没有下标成员
【发布时间】:2017-01-07 06:52:27
【问题描述】:

我目前正在将 C++ 代码转换为 Swift,但我遇到了一个问题。传递给函数的参数是一个字符串,而我遇到困难的地方是尝试根据字符串的倒数第二个字符设置变量以检查某个字符。

错误显示在这一行:

line[i-1]

我尝试将此值转换为 Int 但这不起作用:

Int(line[i - 1])

我还尝试查看采用 Int 的字符串的 startIndex 函数是否可以工作,但它没有:

line.startIndex[i - 1]

这是完整的功能:

func scanStringForSpecificCharacters(line: String){

    var maxOpen: Int = 0;
    var minOpen: Int = 0;

    minOpen = 0;
    maxOpen = 0;
    var i = 0
    while i < line.characters.count {
        for character in line.characters {

            //var c: Character = line[i];
            if character == "(" {
                maxOpen += 1;
                if i == 0 || line[i - 1] != ":" {
                    minOpen += 1;
                }
            }
            else if character == ")"{
                minOpen = max(0,minOpen-1);
                if i == 0 || line[i-1] != ":"{
                    maxOpen -= 1;
                }
                if maxOpen < 0{
                    break;
                }
            }
        }

        if maxOpen >= 0 && minOpen == 0{
            print("YES")
        }else{
            print("NO")
        }
    }
}

【问题讨论】:

  • line.characters[i-1] 也许
  • Xcode 抛出错误 'Cannot subscript a value of type 'String.characterView' with an index of type 'Int''。
  • 看看How does String.Index work in Swift 3——你需要在字符串上使用index(before:)
  • 是的,Hamish 是对的,line.characters.index(before: i)
  • 你真正想要达到什么目的?你的函数计算什么?嵌套循环是故意的吗? – Swift 中可能有更好的方法。

标签: swift


【解决方案1】:

Swift 中的字符串不是索引集合,而是您可以访问以下四种不同视图之一:字符、UTF8、UTF16 或 unicodescalars。

这是因为 Swift 支持 unicode,其中单个字符实际上可能由多个 unicode 标量组成。

这是一个真正帮助我解决这个问题的帖子:https://oleb.net/blog/2016/08/swift-3-strings/

无论如何,要回答您的问题,您需要使用index(after:)index(before:)index(_, offsetBy:) 创建索引。

在你的情况下,你想做这样的事情:

line.index(line.endIndex, offsetBy: -2) // second to last character

此外,您可能会发现直接使用 String.Index 类型而不是 Int 进行迭代更容易:

let line = "hello"

var i = line.startIndex
while i < line.endIndex {
    print(line[i])
    i = line.index(after: i)
}
// prints -> 
// h
// e
// l
// l
// o

【讨论】:

  • 这可能是一个愚蠢的问题,但是否可以像上面那样找到字符串的索引,并将该索引转换回字符串或字符?也许我看错了,没有看到它,但只是想我会问@MathewS
  • 是的!有一个方法 index(of:) 可以找到一个字符的索引:developer.apple.com/reference/swift/string.characterview我从来没有真正使用过它
【解决方案2】:

在 Swift 中使用字符串在其发展过程中发生了数次更改,它看起来一点也不像 C++。您不能为字符串下标来获取单个字符,您应该为此使用索引类。我建议你阅读这篇文章: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html

【讨论】:

    【解决方案3】:

    正如其他答案中已经指出的那样,编译器错误 是由您无法索引 Swift String 的问题引起的 整数。

    您的代码中的另一个问题是您有一个 嵌套循环,它是 可能不是故意的。

    实际上我会尽量避免字符串索引 枚举字符,如果可能的话。在你的情况下,你可以 在单独的变量中轻松跟踪前面的字符:

    var lastChar: Character = " " // Anything except ":"
    
    for char in line.characters {
        if char == "(" {
            maxOpen += 1;
            if lastChar != ":" {
                minOpen += 1;
            }
        }
    
        // ...
    
        lastChar = char
    }
    

    或者,因为您只需要知道前面的字符是否是 冒号:

    var lastIsColon = false
    
    for char in string.characters {
        if char == "(" {
            maxOpen += 1;
            if !lastIsColon {
                minOpen += 1;
            }
        }
    
        // ...
    
        lastIsColon = char == ":"
    }
    

    另一种可能的方法是遍历字符串并移位 并行查看字符串:

    for (lastChar, char) in zip([" ".characters, line.characters].joined(), line.characters) {
    
        // ...
    
    }
    

    【讨论】:

    • +1 直接枚举。我一直在研究一种上下跳跃的算法,我开始将 String.Index 视为锤子
    【解决方案4】:

    正如其他人已经解释的那样,尝试对 Swift 字符串进行索引是一种痛苦。 作为对代码的最小更改,我建议您在前面的行中创建一个字符数组:

    let linechars = Array(line.characters)
    

    然后在需要索引到该行的任何地方,使用linechars

    这个:

    if i == 0 || line[i-1] != ":" {
    

    变成:

    if i == 0 || linechars[i-1] != ":" {
    

    【讨论】:

    • 顺便说一句,你永远不会在你的 while 循环中增加 i
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 2017-01-25
    • 2014-12-17
    相关资源
    最近更新 更多