为什么Swift编译器将此标记为错误?

Faw*_*kes 6 string range subscript swift swift4.2

我有两种编写相同代码的方法,其中一种似乎不受Swift编译器的影响.你能解释一下原因吗?

语境:

let guaranteedValue: String
let cursorPositionFromEnd: Int
Run Code Online (Sandbox Code Playgroud)

工作代码:

let stringFromEndUntilCursorPosition = String(guaranteedValue.reversed()[0..<cursorPositionFromEnd])
Run Code Online (Sandbox Code Playgroud)

非工作代码:

let reversedOriginalString = guaranteedValue.reversed()
let stringFromEndUntilCursorPosition = String(reversedOriginalString[0..<cursorPositionFromEnd])
Run Code Online (Sandbox Code Playgroud)

编译器错误消息:"无法ReversedCollection<String>使用索引类型下标类型的值Range<Int>"

其他工作尝试:

let reversedOriginalString = guaranteedValue.reversed()[0..< cursorPositionFromEnd]
let stringFromEndUntilCursorPosition = String(reversedOriginalString)
Run Code Online (Sandbox Code Playgroud)

基本上这个想法是你只能下一个反转范围{但可能不仅仅}如果你在函数返回时添加索引,但是如果你首先用let或var引用变量然后尝试下标它就不行.

我也明白,如果Range是String.Index类型或者其他任何新方式,它可能会在"非工作代码"中起作用.

有谁能解释为什么?这是Swift编译器中的一个错误,它已经有足够的"扭曲"字符串逻辑吗?

Mar*_*n R 5

有几种reversed()方法,如什么麻烦可以将快速数组的反转()带来解释.

在您的第一个代码示例中,

let stringFromEndUntilCursorPosition = String(guaranteedValue.reversed()[0..<cursorPositionFromEnd])
Run Code Online (Sandbox Code Playgroud)

编译器从Sequence.reversed()需要该方法的上下文(即下标)推断出,该 方法返回一个数组.数组由整数索引,因此代码编译.此方法具有O(n)复杂性,因为会创建包含所有元素的新数组.

let reversedOriginalString = guaranteedValue.reversed()
Run Code Online (Sandbox Code Playgroud)

没有这样的上下文,编译器选择该 Bidirectional.reversed()方法.与上述方法相比,这个方法具有 O(1)复杂性.因此,它返回一个ReversedCollection具有自己的索引类型的东西

let stringFromEndUntilCursorPosition = String(reversedOriginalString[0..<cursorPositionFromEnd])
Run Code Online (Sandbox Code Playgroud)

产生观察到的错误消息.

可能的解决方案:

  • 提供上下文以强制执行数组创建:

    let reversedOriginalString: [Character] = guaranteedValue.reversed()
    // Or: let reversedOriginalString: Array = guaranteedValue.reversed()
    // Or: let reversedOriginalString = guaranteedValue.reversed() as Array
    let stringFromEndUntilCursorPosition = String(reversedOriginalString[0..<cursorPositionFromEnd])
    
    Run Code Online (Sandbox Code Playgroud)

    这有效,但缺点是创建临时数组.

  • 对反向集合进行适当的索引计算:

    let reversedOriginalString = guaranteedValue.reversed()
    let pos = reversedOriginalString.index(reversedOriginalString.startIndex, offsetBy: cursorPositionFromEnd)
    let stringFromEndUntilCursorPosition = String(reversedOriginalString[..<pos])
    
    Run Code Online (Sandbox Code Playgroud)

    这避免了中间数组,但编写起来很繁琐.

  • 使用prefix(maxLength:)序列的方法:

    let reversedOriginalString = guaranteedValue.reversed()
    let stringFromEndUntilCursorPosition = String(reversedOriginalString.prefix(cursorPositionFromEnd))
    
    Run Code Online (Sandbox Code Playgroud)