我一直在更新我的一些旧代码和答案与Swift 3,但当我得到Swift字符串和索引子字符串的事情变得令人困惑。

具体来说,我尝试了以下几点:

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)

第二行给出了如下错误

String类型的值没有成员substringWithRange

我看到String现在确实有以下方法:

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

这些一开始让我很困惑,所以我开始摆弄索引和范围。这是子字符串的后续问题和答案。我在下面添加了一个答案来说明它们是如何使用的。


当前回答

我最初的反应也一样。我也对语法和对象在每个主要版本中发生如此巨大的变化感到沮丧。

然而,我从经验中意识到,我总是在努力对抗“变化”的过程中最终遭受后果,比如处理多字节字符,如果你面对的是全球受众,这是不可避免的。

因此,我决定承认并尊重苹果工程师所付出的努力,并尽我所能,理解他们在想出这种“可怕”方法时的心态。

与其创建扩展,这只是一个让你的生活更容易的解决方案(我不是说他们是错误的或昂贵的),为什么不弄清楚字符串现在是如何设计工作的。

例如,我在Swift 2.2上有这样的代码:

let rString = cString.substringToIndex(2)
let gString = (cString.substringFromIndex(2) as NSString).substringToIndex(2)
let bString = (cString.substringFromIndex(4) as NSString).substringToIndex(2)

在放弃尝试使用相同的方法工作后,例如使用Substrings,我终于理解了将字符串作为双向集合的概念,为此我最终得到了这个版本的相同代码:

let rString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let gString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let bString = String(cString.characters.prefix(2))

我希望这有助于……

其他回答

Swift 5解决方案高性能

let fromIndex = s.index(s.startIndex, offsetBy: fromIndex)
let toIndex = s.index(s.startIndex, offsetBy: toIndex)

我使用这种方法从一个fromIndex到toIndex的Leetcode问题获得子字符串,它超时了,似乎这是非常低效和缓慢的,并导致了超时。

一个更快的纯Swift方式来完成这个是:

let fromIndex = String.Index(utf16Offset:fromIndex, in: s)
let toIndex = String.Index(utf16Offset: toIndex, in: s)

斯威夫特5 let desiredIndex: Int = 7 let substring = str[字符串]。指数(encodedOffset: desiredIndex)…] 这个子字符串变量会给你结果。 这里Int被转换为Index,然后你可以拆分字符串。除非你会得到错误。

谁曾经在Swift中负责字符串,这完全是一团糟,这绝对是该语言最糟糕的特性之一。

一个简单的解决方法是实现这样一个函数(或使它成为一个扩展函数):

func substring(str: String, start: Int, end : Int) -> String
{
    let startIndex = str.index(str.startIndex, offsetBy: start)
    let endIndex = str.index(str.startIndex, offsetBy: end)
    return String(str[startIndex..<endIndex])
}

我最初的反应也一样。我也对语法和对象在每个主要版本中发生如此巨大的变化感到沮丧。

然而,我从经验中意识到,我总是在努力对抗“变化”的过程中最终遭受后果,比如处理多字节字符,如果你面对的是全球受众,这是不可避免的。

因此,我决定承认并尊重苹果工程师所付出的努力,并尽我所能,理解他们在想出这种“可怕”方法时的心态。

与其创建扩展,这只是一个让你的生活更容易的解决方案(我不是说他们是错误的或昂贵的),为什么不弄清楚字符串现在是如何设计工作的。

例如,我在Swift 2.2上有这样的代码:

let rString = cString.substringToIndex(2)
let gString = (cString.substringFromIndex(2) as NSString).substringToIndex(2)
let bString = (cString.substringFromIndex(4) as NSString).substringToIndex(2)

在放弃尝试使用相同的方法工作后,例如使用Substrings,我终于理解了将字符串作为双向集合的概念,为此我最终得到了这个版本的相同代码:

let rString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let gString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let bString = String(cString.characters.prefix(2))

我希望这有助于……

我对Swift的字符串访问模型感到非常沮丧:所有东西都必须是索引。我想要的只是使用Int访问字符串的第I个字符,而不是笨拙的索引和推进(这恰好随着每个主要版本的发布而改变)。所以我对String做了一个扩展:

extension String {
    func index(from: Int) -> Index {
        return self.index(startIndex, offsetBy: from)
    }

    func substring(from: Int) -> String {
        let fromIndex = index(from: from)
        return String(self[fromIndex...])
    }

    func substring(to: Int) -> String {
        let toIndex = index(from: to)
        return String(self[..<toIndex])
    }

    func substring(with r: Range<Int>) -> String {
        let startIndex = index(from: r.lowerBound)
        let endIndex = index(from: r.upperBound)
        return String(self[startIndex..<endIndex])
    }
}

let str = "Hello, playground"
print(str.substring(from: 7))         // playground
print(str.substring(to: 5))           // Hello
print(str.substring(with: 7..<11))    // play