swift 'subscript'无法使用:无法使用CountableClosedRange为字符串添加下标< Int>,有关讨论,请参阅文档注解

oprakyz7  于 2022-12-10  发布在  Swift
关注(0)|答案(9)|浏览(136)

在Swift 4中,当我尝试使用下标语法获取StringSubstring时,会出现此错误。
'subscript'无法使用:无法使用CountableClosedRange为字符串添加下标,有关讨论,请参阅文档注解
例如:

let myString: String = "foobar"
let mySubstring: Substring = myString[1..<3]

两个问题:
1.如何解决此错误?
1.错误中提到的“供讨论的文档注解”在哪里?

z9ju0rcb

z9ju0rcb1#

1.如果你想在字符串上使用下标,比如"palindrome"[1..<3]"palindrome"[1...3],请使用这些扩展。

雨燕4

extension String {
    subscript (bounds: CountableClosedRange<Int>) -> String {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(startIndex, offsetBy: bounds.upperBound)
        return String(self[start...end])
    }

    subscript (bounds: CountableRange<Int>) -> String {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(startIndex, offsetBy: bounds.upperBound)
        return String(self[start..<end])
    }
}

雨燕3

对于Swift 3,替换为return self[start...end]return self[start..<end]
1.苹果没有在Swift语言中内置这一功能,因为“字符”的定义取决于String的编码方式。字符可以是8到64位,默认值通常是UTF-16。你可以在String.Index中指定其他String编码。
这是Xcode错误所参考的文稿。
More on String encodings like UTF-8 and UTF-16

a0x5cqrl

a0x5cqrl2#

您的问题(和自我答案)有2个问题:
Swift的标准库中从来没有提供过用Int下标字符串的功能。只要Swift存在,这段代码就一直无效:

let mySubstring: Substring = myString[1..<3]

新的String.Index(encodedOffset: )返回一个UTF-16(16位)编码的索引,Swift的字符串使用 Extended Grapheme Cluster,它可以用8到64位来存储一个字符,Emojis是一个很好的演示:

let myString = "🇺🇸🇨🇦🇬🇧🇫🇷"
let lowerBound = String.Index(encodedOffset: 1)
let upperBound = String.Index(encodedOffset: 3)
let mySubstring = myString[lowerBound..<upperBound]

// Expected: Canadian and UK flags
// Actual  : gibberish
print(mySubstring)

事实上,在Swift 4中,无论是好是坏,String.Index都没有发生任何变化:

let myString = "🇺🇸🇨🇦🇬🇧🇫🇷"
let lowerBound = myString.index(myString.startIndex, offsetBy: 1)
let upperBound = myString.index(myString.startIndex, offsetBy: 3)
let mySubstring = myString[lowerBound..<upperBound]

print(mySubstring)
km0tfn4u

km0tfn4u3#

您可以将字符串转换为字符数组...

let aryChar = Array(myString)

然后您就可以获得所有阵列功能...

wz3gfoph

wz3gfoph4#

1.如何解决此错误?
这个错误意味着你不能在下标格式中使用Int--你必须使用String.Index,你可以用encodedOffset Int初始化它。

let myString: String = "foobar"
let lowerBound = String.Index.init(encodedOffset: 1)
let upperBound = String.Index.init(encodedOffset: 3)
let mySubstring: Substring = myString[lowerBound..<upperBound]

1.错误中提到的“供讨论的文档注解”在哪里?
它在GitHub的Swift标准库中的一个名为UnavailableStringAPIs.swift.gyb的文件中,位于一个锁着的文件柜的底部,这个文件柜被卡在一个废弃的厕所里,门上有一个标志,上面写着“当心豹子”。链接

ryhaxcpt

ryhaxcpt5#

基于p-sun's answer

雨燕4

extension StringProtocol {
    subscript(bounds: CountableClosedRange<Int>) -> SubSequence {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(start, offsetBy: bounds.count)
        return self[start..<end]
    }

    subscript(bounds: CountableRange<Int>) -> SubSequence {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(start, offsetBy: bounds.count)
        return self[start..<end]
    }
}

显著变化:

  • 现在是StringProtocol的扩展。这允许Substring等采用者也获得这些下标。
  • 如果在String的起始处遍历一个字符串,那么这个方法的时间复杂度为O(n),其中n是从i开始的偏移量。
lrl1mhuk

lrl1mhuk6#

p-sun'sJustin Oroz's的基础上,这里有两个扩展,可以防止字符串开头和结尾以外的无效索引(这些扩展还可以避免只为了找到范围结尾的索引而从开头重新扫描字符串):

extension String {

    subscript(bounds: CountableClosedRange<Int>) -> String {
        let lowerBound = max(0, bounds.lowerBound)
        guard lowerBound < self.count else { return "" }

        let upperBound = min(bounds.upperBound, self.count-1)
        guard upperBound >= 0 else { return "" }

        let i = index(startIndex, offsetBy: lowerBound)
        let j = index(i, offsetBy: upperBound-lowerBound)

        return String(self[i...j])
    }

    subscript(bounds: CountableRange<Int>) -> String {
        let lowerBound = max(0, bounds.lowerBound)
        guard lowerBound < self.count else { return "" }

        let upperBound = min(bounds.upperBound, self.count)
        guard upperBound >= 0 else { return "" }

        let i = index(startIndex, offsetBy: lowerBound)
        let j = index(i, offsetBy: upperBound-lowerBound)

        return String(self[i..<j])
    }
}
zzoitvuj

zzoitvuj7#

p-sun'sJustin Oroz's答案的改进代码:
您可以:
第一个
代码在任何情况下都能很好地工作:

u0sqgete

u0sqgete8#

extension String {

    subscript(bounds: CountableClosedRange<Int>) -> String {
        let lowerBound = max(0, bounds.lowerBound)
        guard lowerBound < self.count else { return "" }

        let upperBound = min(bounds.upperBound, self.count-1)
        guard upperBound >= 0 else { return "" }

        let i = index(startIndex, offsetBy: lowerBound)
        let j = index(i, offsetBy: upperBound-lowerBound)

        return String(self[i...j])
    }

    subscript(bounds: CountableRange<Int>) -> String {
        let lowerBound = max(0, bounds.lowerBound)
        guard lowerBound < self.count else { return "" }

        ***let upperBound = min(bounds.upperBound, self.count-1)***
        guard upperBound >= 0 else { return "" }

        let i = index(startIndex, offsetBy: lowerBound)
        let j = index(i, offsetBy: upperBound-lowerBound)

        return String(self[i..<j])
    }
}
pdsfdshx

pdsfdshx9#

出现此错误是因为带范围的下标的结果是Substring?,而不是Substring
您必须使用下列程式码:

let myString: String = "foobar"
let mySubstring: Substring? = myString[1..<3]

相关问题