我一直在更新我的一些旧代码和答案与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的字符串访问模型感到非常沮丧:所有东西都必须是索引。我想要的只是使用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

其他回答

我发现了这个相当简单的方法。

var str = "Hello, World"
let arrStr = Array(str)
print(arrStr[0..<5]) //["H", "e", "l", "l", "o"]
print(arrStr[7..<12]) //["W", "o", "r", "l", "d"]
print(String(arrStr[0..<5])) //Hello
print(String(arrStr[7..<12])) //World

下面是一个更通用的实现:

这种技术仍然使用索引来保持Swift的标准,并暗示一个完整的字符。

extension String
{
    func subString <R> (_ range: R) -> String? where R : RangeExpression, String.Index == R.Bound
    {
        return String(self[range])
    }

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

从第3个字符开始子字符串:

let item = "Fred looks funny"
item.subString(item.index(at: 2)...) // "ed looks funny"

我已经使用驼峰subString表示它返回一个字符串,而不是一个subString。

我的思维很机械。以下是一些基本常识……

斯威夫特4 斯威夫特5

  let t = "abracadabra"

  let start1 = t.index(t.startIndex, offsetBy:0)
  let   end1 = t.index(t.endIndex, offsetBy:-5)
  let start2 = t.index(t.endIndex, offsetBy:-5)
  let   end2 = t.index(t.endIndex, offsetBy:0)

  let t2 = t[start1 ..< end1]
  let t3 = t[start2 ..< end2]                

  //or a shorter form 

  let t4 = t[..<end1]
  let t5 = t[start2...]

  print("\(t2) \(t3) \(t)")
  print("\(t4) \(t5) \(t)")

  // result:
  // abraca dabra abracadabra

结果是一个子字符串,这意味着它是原始字符串的一部分。要得到一个完整的独立字符串,只需使用e.g.。

    String(t3)
    String(t4)

这是我所使用的:

    let mid = t.index(t.endIndex, offsetBy:-5)
    let firstHalf = t[..<mid]
    let secondHalf = t[mid...]

斯威夫特4

extension String {
    subscript(_ i: Int) -> String {
        let idx1 = index(startIndex, offsetBy: i)
        let idx2 = index(idx1, offsetBy: 1)
        return String(self[idx1..<idx2])
    }
}

let s = "hello"

s[0]    // h
s[1]    // e
s[2]    // l
s[3]    // l
s[4]    // o

我创建了这样一个简单的函数:

func sliceString(str: String, start: Int, end: Int) -> String {
    let data = Array(str)
    return String(data[start..<end])
}

你可以用以下方法来使用它

print(sliceString(str: "0123456789", start: 0, end: 3)) // -> prints 012