ChatGPT解决这个技术问题 Extra ChatGPT

你如何使用 String.substringWithRange? (或者,范围如何在 Swift 中工作?)

我还没有弄清楚如何在 Swift 中获取 String 的子字符串:

var str = “Hello, playground”
func test(str: String) -> String {
 return str.substringWithRange( /* What goes here? */ )
}
test (str)

我无法在 Swift 中创建 Range。 Playground 中的自动完成功能并不是很有帮助 - 这就是它的建议:

return str.substringWithRange(aRange: Range<String.Index>)

我在 Swift 标准参考库中没有找到任何有用的东西。这是另一个疯狂的猜测:

return str.substringWithRange(Range(0, 1))

和这个:

let r:Range<String.Index> = Range<String.Index>(start: 0, end: 2)
return str.substringWithRange(r)

我看到其他答案 (Finding index of character in Swift String) 似乎表明由于 StringNSString 的桥接类型,“旧”方法应该可以工作,但不清楚如何 - 例如,这不起作用要么(似乎不是有效的语法):

let x = str.substringWithRange(NSMakeRange(0, 3))

想法?

当您说最后一个示例不起作用时,您是什么意思?它会导致错误或返回意外值吗?
请欺骗 rdar://17158813 请求下标符号 openradar.appspot.com/radar?id=6373877630369792

m
matt---

您可以使用 substringWithRange 方法。它需要一个开始和结束 String.Index。

var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex, end: str.endIndex)) //"Hello, playground"

要更改开始和结束索引,请使用 advancedBy(n)。

var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex.advancedBy(2), end: str.endIndex.advancedBy(-1))) //"llo, playgroun"

你仍然可以在 NSRange 中使用 NSString 方法,但是你必须确保你使用的是这样的 NSString:

let myNSString = str as NSString
myNSString.substringWithRange(NSRange(location: 0, length: 3))

注意:正如 JanX2 提到的,第二种方法对于 unicode 字符串是不安全的。


是的。现在我会在必要时继续桥接到 NSString 。看来斯威夫特的字符串仍然不完整
这不安全!您假设 String 和 NSString 的索引是可互换的。事实并非如此。 String 的索引指的是 Unicode 代码点,而 NSString 的索引指的是 UTF-16 代码单元!用表情符号试试。
请注意,字符串中的索引不再引用 Unicode 代码点。将它们视为引用用户感知的字符。
那么这里的正确答案是什么?调用 advance 意味着我们必须遍历一个可能很长的字符串。但是形成一个 NSRange 并明确使用 NSString 是危险的吗?还剩下什么?
谢谢,m8。在只做 Objective-C 4 年后,这种向 Swift 的过渡有点混乱。
W
Warif Akhand Rishi

斯威夫特 2

简单的

let str = "My String"
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)]
//"Strin"

斯威夫特 3

let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)

str[startIndex...endIndex]       // "Strin"
str.substring(to: startIndex)    // "My "
str.substring(from: startIndex)  // "String"

斯威夫特 4

substring(to:)substring(from:)Swift 4 中已弃用。

String(str[..<startIndex])    // "My "
String(str[startIndex...])    // "String"
String(str[startIndex...endIndex])    // "Strin"

这个。如此令人困惑,以至于您必须先找到索引才能使用它。不知道为什么我花了这么长时间才意识到,但感谢您对人类的贡献。
在 swift 中,4 个子字符串操作返回一个子字符串类型的实例,而不是字符串。需要将结果转换为字符串以便长期存储。让 newString = 字符串(子字符串)
M
Mabedan

注意:@airspeedswift 对这种方法的权衡做出了一些very insightful points,特别是隐藏的性能影响。字符串不是简单的野兽,获取特定索引可能需要 O(n) 时间,这意味着使用下标的循环可能是 O(n^2)。您已收到警告。

您只需添加一个新的 subscript 函数,该函数接受一个范围并使用 advancedBy() 走到您想要的位置:

import Foundation

extension String {
    subscript (r: Range<Int>) -> String {
        get {
            let startIndex = self.startIndex.advancedBy(r.startIndex)
            let endIndex = startIndex.advancedBy(r.endIndex - r.startIndex)

            return self[Range(start: startIndex, end: endIndex)]
        }
    }
}

var s = "Hello, playground"

println(s[0...5]) // ==> "Hello,"
println(s[0..<5]) // ==> "Hello"

(这绝对应该是语言的一部分。请欺骗 rdar://17158813

为了好玩,您还可以将 + 运算符添加到索引中:

func +<T: ForwardIndex>(var index: T, var count: Int) -> T {
  for (; count > 0; --count) {
    index = index.succ()
  }
  return index
}

s.substringWithRange(s.startIndex+2 .. s.startIndex+5)

(我还不知道这是否应该成为语言的一部分。)


出于性能原因,我们可能应该尽可能使用 String.Index 而不是整数索引。从整数索引到 String.Index 的每次转换都需要处理要查找的字符串。
@AndrewDunn 这不是过早的优化。从整数索引到 String.Index 的每次转换都是 O(n),而不是 O(1)!请阅读 Swift 命名空间中 advance<T>(…) 的注释。
整个 String 实现是使用 String.Index 完成的。在这种情况下,优化不如保持一切简单。必须在 int 和 String.Index 之间来回切换会导致混乱。
@chakrit 仅当您需要使用的索引还不是整数(而不是 String.Indexes)时,通常是这种情况。比您只希望所有这些字符串处理方法都与 Int 一起使用。而且您被迫将其转换为 String.Indexes,这会导致您提到的混乱。
感兴趣的读者应该看看 ExSwift github.com/pNre/ExSwift
G
Glenn Posadas

在我写这篇文章的时候,没有一个扩展是完全兼容 Swift 4.2 的,所以这里有一个可以满足我能想到的所有需求:

extension String {
    func substring(from: Int?, to: Int?) -> String {
        if let start = from {
            guard start < self.count else {
                return ""
            }
        }

        if let end = to {
            guard end >= 0 else {
                return ""
            }
        }

        if let start = from, let end = to {
            guard end - start >= 0 else {
                return ""
            }
        }

        let startIndex: String.Index
        if let start = from, start >= 0 {
            startIndex = self.index(self.startIndex, offsetBy: start)
        } else {
            startIndex = self.startIndex
        }

        let endIndex: String.Index
        if let end = to, end >= 0, end < self.count {
            endIndex = self.index(self.startIndex, offsetBy: end + 1)
        } else {
            endIndex = self.endIndex
        }

        return String(self[startIndex ..< endIndex])
    }

    func substring(from: Int) -> String {
        return self.substring(from: from, to: nil)
    }

    func substring(to: Int) -> String {
        return self.substring(from: nil, to: to)
    }

    func substring(from: Int?, length: Int) -> String {
        guard length > 0 else {
            return ""
        }

        let end: Int
        if let start = from, start > 0 {
            end = start + length - 1
        } else {
            end = length - 1
        }

        return self.substring(from: from, to: end)
    }

    func substring(length: Int, to: Int?) -> String {
        guard let end = to, end > 0, length > 0 else {
            return ""
        }

        let start: Int
        if let end = to, end - length > 0 {
            start = end - length + 1
        } else {
            start = 0
        }

        return self.substring(from: start, to: to)
    }
}

然后,您可以使用:

let string = "Hello,World!"

string.substring(from: 1, to: 7)让您:ello,Wo

string.substring(to: 7)让您:Hello,Wo

string.substring(from: 3)让您:lo,World!

string.substring(from: 1, length: 4)让您:ello

string.substring(length: 4, to: 7)让您:o,Wo

更新了 substring(from: Int?, length: Int) 以支持从零开始。


这如何处理表情符号和扩展字素簇? (我应该自己测试一下,但目前不方便。)
@Suragch 它处理得很好:"Hello😇😍😘😎📸📀💾∝ℵℶ≹".substring(from: 4, to: 14) 给了我们:o😇😍😘😎📸📀💾∝ℵℶ
不过,这些看起来像普通字符。尝试使用👩‍👩‍👧‍👦或🇨🇦🇺🇸🇲🇽等表情符号
p
phnmnn

斯威夫特 2.0

简单的:

let myString = "full text container"
let substring = myString[myString.startIndex..<myString.startIndex.advancedBy(3)] // prints: ful

斯威夫特 3.0

let substring = myString[myString.startIndex..<myString.index(myString.startIndex, offsetBy: 3)] // prints: ful

斯威夫特 4.0

Substring 操作返回 Substring 类型的实例,而不是 String。

let substring = myString[myString.startIndex..<myString.index(myString.startIndex, offsetBy: 3)] // prints: ful

// Convert the result to a String for long-term storage.
let newString = String(substring)

遗憾的是,从 Xcode 8 beta 6 起不再与 Swift 3 兼容
为我工作。 Xcode 8,Swift 3。不是 Mac OS Sierra 上的测试版。 text[text.startIndex..<text.index(text.startIndex, offsetBy: 2)]
C
Community

一旦找到正确的语法,它比这里的任何答案都简单得多。

我想去掉 [ 和 ]

let myString = "[ABCDEFGHI]"
let startIndex = advance(myString.startIndex, 1) //advance as much as you like
let endIndex = advance(myString.endIndex, -1)
let range = startIndex..<endIndex
let myNewString = myString.substringWithRange( range )

结果将是“ABCDEFGHI” startIndex 和 endIndex 也可以用于

let mySubString = myString.substringFromIndex(startIndex)

等等!

PS:如备注所示,xcode 7 和 iOS9 自带的 swift 2 有一些语法变化!

请看这个page


是的,我有同样的问题,调试器没有多次显示正确的字符串?
我有一个这样的字符串 /Date(147410000000)/。我怎样才能获得价值而不是指定索引。我需要使用 rangeOfString("(") 和 rangeOfString(")") 获取值。结果应该是 147410000000。我能得到那个
这并不难:var str = "/Date(147410000000)/." var range = str.rangeOfString("(")!.endIndex..
由于 Xcode 7 beta 6 advance(myString.endIndex, -1) 语法已更改为 myString.endIndex.advancedBy(-1)
J
Joris Kluivers

例如,在我的全名中查找名字(直到第一个空格):

let name = "Joris Kluivers"

let start = name.startIndex
let end = find(name, " ")

if end {
    let firstName = name[start..end!]
} else {
    // no space found
}

startend 在此处属于 String.Index 类型,用于创建 Range<String.Index> 并在下标访问器中使用(如果在原始字符串中完全找到空格)。

很难直接从开头帖子中使用的整数位置创建 String.Index。这是因为在我的名字中,每个字符的字节大小都是相等的。但是在其他语言中使用特殊重音的字符可能会使用更多的字节(取决于使用的编码)。那么整数应该指哪个字节呢?

可以使用方法 succpred 从现有的 String.Index 创建一个新的 String.Index,这将确保跳过正确的字节数以到达编码中的下一个代码点。但是在这种情况下,搜索字符串中第一个空格的索引以找到结束索引会更容易。


C
Community

由于 String 是 NSString 的桥接类型,因此“旧”方法应该可以工作,但不清楚如何 - 例如,这也不起作用(似乎不是有效的语法): let x = str.substringWithRange(NSMakeRange (0, 3))

对我来说,这是你问题中真正有趣的部分。 String 桥接到 NSString,所以大多数 NSString 方法都直接在 String 上工作。您可以不假思索地自由使用它们。因此,例如,这就像您期望的那样工作:

// delete all spaces from Swift String stateName
stateName = stateName.stringByReplacingOccurrencesOfString(" ", withString:"")

但是,正如经常发生的那样,“我的魔力起作用了,但它对你不起作用。”您只是碰巧选择了一种罕见的情况,其中存在一个并行的同名 Swift 方法,在这种情况下,Swift 方法使 Objective-C 方法黯然失色。因此,当你说 str.substringWithRange 时,Swift 认为你指的是 Swift 方法而不是 NSString 方法——然后你就被淹没了,因为 Swift 方法需要一个 Range<String.Index>,而你不知道如何制作其中一个.

最简单的方法是通过显式强制转换来阻止 Swift 像这样被掩盖:

let x = (str as NSString).substringWithRange(NSMakeRange(0, 3))

请注意,此处不涉及任何重要的额外工作。 “Cast”并不意味着“convert”; String 实际上是一个 NSString。我们只是告诉 Swift 为了这一行代码的目的如何查看这个变量。

整个事情真正奇怪的部分是导致所有这些麻烦的 Swift 方法没有记录。我不知道它是在哪里定义的;它不在 NSString 标头中,也不在 Swift 标头中。


但是,我建议提交一个错误。 Apple 应该“钓鱼或诱饵” - 要么给我们一种构建 Range<String.Index> 的方法,要么让我们摆脱这种未记录的方法。
该死的——这很有用。尽管文档说了什么,但直到我读到这篇文章,我才明白出了什么问题。现在排序:)
N
Nate Cook

简短的回答是,现在这在 Swift 中真的很难。我的预感是,Apple 仍有大量工作要做,以便为此类事情提供便利方法。

String.substringWithRange() 需要一个 Range<String.Index> 参数,据我所知,没有 String.Index 类型的生成器方法。您可以从 aString.startIndexaString.endIndex 取回 String.Index 值并调用 .succ().pred() ,但这太疯狂了。

使用旧的 Int 对 String 类进行扩展怎么样?

extension String {
    subscript (r: Range<Int>) -> String {
        get {
            let subStart = advance(self.startIndex, r.startIndex, self.endIndex)
            let subEnd = advance(subStart, r.endIndex - r.startIndex, self.endIndex)
            return self.substringWithRange(Range(start: subStart, end: subEnd))
        }
    }
    func substring(from: Int) -> String {
        let end = countElements(self)
        return self[from..<end]
    }
    func substring(from: Int, length: Int) -> String {
        let end = from + length
        return self[from..<end]
    }
}

let mobyDick = "Call me Ishmael."
println(mobyDick[8...14])             // Ishmael

let dogString = "This 🐶's name is Patch."
println(dogString[5..<6])               // 🐶
println(dogString[5...5])              // 🐶
println(dogString.substring(5))        // 🐶's name is Patch.
println(dogString.substring(5, length: 1))   // 🐶

更新:Swift beta 4 解决了以下问题!

就目前而言 [在 beta 3 和更早版本中],即使是 Swift 原生字符串在处理 Unicode 字符方面也存在一些问题。上面的狗图标有效,但以下无效:

let harderString = "1:1️⃣"
for character in harderString {
    println(character)
}

输出:

1
:
1
️
⃣

奇怪的是,核心 Swift 类似乎缺少很多基本功能。我认为 Apple 不希望我们不断引用 Foundation 类来执行简单的任务。
完全。请记住,Swift 基本上是在黑暗中开发的,每个人对“简单任务”都有不同的定义——我敢打赌,我们会在这些问题上看到一些快速迭代。
@JanX2 - 谢谢,你完全正确。与 NSString 的无缝桥接让我觉得我只使用了 Swift 原生的 String 方法,因为我没有使用任何 myString as NSString 调用。
现在在 Swift 原生字符串处理中也存在一些 Unicode 错误:请参阅最后的注释。
@NateCook 你可以为这个问题提交一份雷达吗?
C
Claudio Guirunas

在新的 Xcode 7.0 中使用

//: Playground - noun: a place where people can play

import UIKit

var name = "How do you use String.substringWithRange?"
let range = name.startIndex.advancedBy(0)..<name.startIndex.advancedBy(10)
name.substringWithRange(range)

//OUT:

https://i.stack.imgur.com/1wYAl.png


.advancedBy(0) 对于 startIndex 不是必需的。
C
ChikabuZ

您可以使用此扩展来改进 substringWithRange

斯威夫特 2.3

extension String
{   
    func substringWithRange(start: Int, end: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if end < 0 || end > self.characters.count
        {
            print("end index \(end) out of bounds")
            return ""
        }
        let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(end))
        return self.substringWithRange(range)
    }

    func substringWithRange(start: Int, location: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if location < 0 || start + location > self.characters.count
        {
            print("end index \(start + location) out of bounds")
            return ""
        }
        let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(start + location))
        return self.substringWithRange(range)
    }
}

斯威夫特 3

extension String
{
    func substring(start: Int, end: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if end < 0 || end > self.characters.count
        {
            print("end index \(end) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: end)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }

    func substring(start: Int, location: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if location < 0 || start + location > self.characters.count
        {
            print("end index \(start + location) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: start + location)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }
}

用法:

let str = "Hello, playground"

let substring1 = str.substringWithRange(0, end: 5) //Hello
let substring2 = str.substringWithRange(7, location: 10) //playground

U
Umang Kothari

如何在 Swift 2.0 中获取子字符串的示例代码

(i) 起始索引的子串

输入:-

var str = "Swift is very powerful language!"
print(str)

str = str.substringToIndex(str.startIndex.advancedBy(5))
print(str)

输出:-

Swift is very powerful language!
Swift

(ii) 来自特定索引的子串

输入:-

var str = "Swift is very powerful language!"
print(str)

str = str.substringFromIndex(str.startIndex.advancedBy(6)).substringToIndex(str.startIndex.advancedBy(2))
print(str)

输出:-

Swift is very powerful language!
is

我希望它会帮助你!


O
Oliver Dixon

用很少的代码简单的解决方案。

制作一个包含几乎所有其他语言都有的基本 subStringing 的扩展:

extension String {
    func subString(start: Int, end: Int) -> String {
        let startIndex = self.index(self.startIndex, offsetBy: start)
        let endIndex = self.index(startIndex, offsetBy: end)

        let finalString = self.substring(from: startIndex)
        return finalString.substring(to: endIndex)
    }
}

只需调用它

someString.subString(start: 0, end: 6)

'end' 参数在这里实际上意味着长度,所以我认为它应该重命名为。
我认为使用长度相当混乱。实际上,它是您希望 subString 所在位置的“结束”,而不是 subStrings 结果的实际长度。
p
patrykens

这适用于我的操场:)

String(seq: Array(str)[2...4])

实际上这比调用 advance 更有效
它在我的 Xcode 7 (Swift 2) 操场上不起作用,但这确实... 'var str = "Hello, playground"' String(Array(str.characters)[7]) // "p" String(Array( str.characters)[7...10]) // "播放" String(Array(str.characters)[7..<10]) // "pla"
F
Firo

为 Xcode 7 更新。添加字符串扩展:

利用:

var chuck: String = "Hello Chuck Norris"
chuck[6...11] // => Chuck

执行:

extension String {

    /**
     Subscript to allow for quick String substrings ["Hello"][0...1] = "He"
     */
    subscript (r: Range<Int>) -> String {
        get {
            let start = self.startIndex.advancedBy(r.startIndex)
            let end = self.startIndex.advancedBy(r.endIndex - 1)
            return self.substringWithRange(start..<end)
        }
    }

}

P
Peter Roberts

在操场上试试这个

var str:String = "Hello, playground"

let range = Range(start:advance(str.startIndex,1), end: advance(str.startIndex,8))

它会给你“你好,p”

但是,真正有趣的是,如果您使最后一个索引大于 Playground 中的字符串,它将显示您在 str 之后定义的任何字符串:o

Range() 似乎是一个通用函数,因此它需要知道它正在处理的类型。

您还必须为它提供您对游乐场感兴趣的实际字符串,因为它似乎将所有的字符串一个接一个地保存在一个序列中,然后使用它们的变量名。

所以

var str:String = "Hello, playground"

var str2:String = "I'm the next string"

let range = Range(start:advance(str.startIndex,1), end: advance(str.startIndex,49))

给出“你好,playground�str���我是下一个字符串�str2�”

即使 str2 用 let 定义也有效

:)


我同意它与 Objective-C 相比是冗长的,但是它都适合一行,这是一个奖励。
好吧,仍然缺少一行,它实际上打印出给定您计算的范围的子字符串。我喜欢其他一些使用您的逻辑创建 String 类扩展的解决方案,但在扩展中。这最终是我采用的解决方案。
他们已经修复了您可以超出字符串末尾的错误。现在你只能输入一个值直到 str.endIndex
i
ipraba

Rob Napier 已经使用下标给出了一个很棒的答案。但我觉得有一个缺点,因为没有检查越界条件。这可能会崩溃。所以我修改了扩展名,就在这里

extension String {
    subscript (r: Range<Int>) -> String? { //Optional String as return value
        get {
            let stringCount = self.characters.count as Int
            //Check for out of boundary condition
            if (stringCount < r.endIndex) || (stringCount < r.startIndex){
                return nil
            }
            let startIndex = self.startIndex.advancedBy(r.startIndex)

            let endIndex = self.startIndex.advancedBy(r.endIndex - r.startIndex)

            return self[Range(start: startIndex, end: endIndex)]
        }
    }
}

下面的输出

var str2 = "Hello, World"

var str3 = str2[0...5]
//Hello,
var str4 = str2[0..<5]
//Hello
var str5 = str2[0..<15]
//nil

所以我建议总是检查 if let

if let string = str[0...5]
{
    //Manipulate your string safely
}

你有一个错误 - endIndex 应该是 endIndex 单独的 startIndex,而不是索引之间的距离。
S
Sandu

在 Swift3 中

例如:变量“Duke James Thomas”,我们需要得到“James”。

let name = "Duke James Thomas"
let range: Range<String.Index> = name.range(of:"James")!
let lastrange: Range<String.Index> = img.range(of:"Thomas")!
var middlename = name[range.lowerBound..<lstrange.lowerBound]
print (middlename)

A
Albert Bori

借鉴 Rob Napier 的经验,我开发了这些 Common String Extensions,其中两个是:

subscript (r: Range<Int>) -> String
{
    get {
        let startIndex = advance(self.startIndex, r.startIndex)
        let endIndex = advance(self.startIndex, r.endIndex - 1)

        return self[Range(start: startIndex, end: endIndex)]
    }
}

func subString(startIndex: Int, length: Int) -> String
{
    var start = advance(self.startIndex, startIndex)
    var end = advance(self.startIndex, startIndex + length)
    return self.substringWithRange(Range<String.Index>(start: start, end: end))
}

用法:

"Awesome"[3...7] //"some"
"Awesome".subString(3, length: 4) //"some"

由于类型推断,您可以使用 Range 而不是 Range<String.Index>
C
Community

这是从字符串中获取范围的方式:

var str = "Hello, playground"

let startIndex = advance(str.startIndex, 1)
let endIndex = advance(startIndex, 8)
let range = startIndex..<endIndex
let substr = str[range] //"ello, pl"

关键是您传递的是 String.Index 类型的值范围(这是 Advance 返回的值)而不是整数。

这是必要的,因为 Swift 中的字符串没有随机访问(因为基本上 Unicode 字符的长度可变)。你也不能做str[1]。 String.Index 旨在与它们的内部结构一起工作。

不过,您可以创建一个带有下标的扩展,它会为您执行此操作,因此您可以只传递一个整数范围(参见例如 Rob Napier's answer)。


f
funct7

我试图想出一些 Pythonic 的东西。

这里所有的下标都很棒,但是我真正需要一些简单的东西的时候通常是我想从后面数,例如 string.endIndex.advancedBy(-1)

它支持开始索引和结束索引的 nil 值,其中 nil 表示开始索引为 0,结束索引为 string.characters.count

extension String {
    var subString: (Int?) -> (Int?) -> String {
        return { (start) in
            { (end) in
                let startIndex = start ?? 0 < 0 ? self.endIndex.advancedBy(start!) : self.startIndex.advancedBy(start ?? 0)
                let endIndex = end ?? self.characters.count < 0 ? self.endIndex.advancedBy(end!) : self.startIndex.advancedBy(end ?? self.characters.count)

                return startIndex > endIndex ? "" : self.substringWithRange(startIndex ..< endIndex)
            }
        }
    }
}

let dog = "Dog‼🐶"
print(dog.subString(nil)(-1)) // Dog!!

编辑

更优雅的解决方案:

public extension String {
    struct Substring {
        var start: Int?
        var string: String

        public subscript(end: Int?) -> String {
            let startIndex = start ?? 0 < 0 ? string.endIndex.advancedBy(start!) : string.startIndex.advancedBy(start ?? 0)
            let endIndex = end ?? string.characters.count < 0 ? string.endIndex.advancedBy(end!) : string.startIndex.advancedBy(end ?? string.characters.count)

            return startIndex > endIndex ? "" : string.substringWithRange(startIndex ..< endIndex)
        }
    }

    public subscript(start: Int?) -> Substring {
        return Substring(start: start, string: self)
    }
}

let dog = "Dog‼🐶"
print(dog[nil][-1]) // Dog!!

J
Johannes

首先创建范围,然后创建子字符串。您可以像这样使用 fromIndex..<toIndex 语法:

let range = fullString.startIndex..<fullString.startIndex.advancedBy(15) // 15 first characters of the string
let substring = fullString.substringWithRange(range)

H
Hardik Thakkar

这是一个从整个 URL 快速获取 video-Id .ie (6oL687G0Iso) 的示例

let str = "https://www.youtube.com/watch?v=6oL687G0Iso&list=PLKmzL8Ib1gsT-5LN3V2h2H14wyBZTyvVL&index=2"
var arrSaprate = str.componentsSeparatedByString("v=")
let start = arrSaprate[1]
let rangeOfID = Range(start: start.startIndex,end:start.startIndex.advancedBy(11))
let substring = start[rangeOfID]
print(substring)

S
Svitlana
let startIndex = text.startIndex
var range = startIndex.advancedBy(1) ..< text.endIndex.advancedBy(-4)
let substring = text.substringWithRange(range)

您可以看到的完整示例 here


s
swiftmb

http://www.learnswiftonline.com/reference-guides/string-reference-guide-for-swift/ 表明这很有效:

var str = "abcd"
str = str.substringToIndex(1)

Playground 执行失败:错误::23:5:错误:类型“String.Index”不符合协议“IntegerLiteralConvertible”str = str.substringToIndex(1) ^
s
sittisal

好吧,我遇到了同样的问题并用“bridgeToObjectiveC()”函数解决了:

var helloworld = "Hello World!"
var world = helloworld.bridgeToObjectiveC().substringWithRange(NSMakeRange(6,6))
println("\(world)") // should print World!

请注意,在示例中,substringWithRange 与 NSMakeRange 结合使用从索引 6 开始(字符“W”)并在索引 6 + 6 位置结束(字符“!”)结束的字符串部分

干杯。


我讨厌这个,但它似乎是 Beta 4 中唯一对我有用的东西。
W
William Falcon

您可以在我编写的 Swift 字符串扩展中使用任何子字符串方法 https://bit.ly/JString

var string = "hello"
var sub = string.substringFrom(3) // or string[3...5]
println(sub)// "lo"

j
joslinm

如果您有 NSRange,则可以无缝桥接到 NSString。例如,我正在使用 UITextFieldDelegate 做一些工作,当它询问是否应该替换范围时,我很快想计算新的字符串值。

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
    println("Got new string: ", newString)
}

B
Bartłomiej Semańczyk

String 的简单扩展

extension String {

    func substringToIndex(index: Int) -> String {
        return self[startIndex...startIndex.advancedBy(min(index, characters.count - 1))]
    }
}

J
Jiachen Ren

如果你不关心性能......这可能是 Swift 4 中最简洁的解决方案

extension String {
    subscript(range: CountableClosedRange<Int>) -> String {
        return enumerated().filter{$0.offset >= range.first! && $0.offset < range.last!}
            .reduce(""){$0 + String($1.element)}
    }
}

它使您能够执行以下操作:

let myStr = "abcd"
myStr[0..<2] // produces "ab"