您如何使用String.substringWithRange?(或Ranges如何在Swift中工作?)


266

我还不能弄清楚如何String在Swift中获取a的子字符串:

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

我无法在Swift中创建范围。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)

我看过其他答案(在Swift String中查找字符的索引),似乎暗示着既然String是的桥类型NSString,“旧”方法应该可以工作,但尚不清楚如何-例如,这也不起作用(似乎不是有效的语法):

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

有什么想法吗?


您说最后一个示例不起作用是什么意思?它会导致错误还是返回意外值?
67樱桃2014年

请复制rdar:// 17158813请求下标符号openradar.appspot.com/radar?id=6373877630369792
Rob Napier

Answers:


259

您可以使用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"

您还可以将NSString方法与NSRange一起使用,但是必须确保使用的NSString是这样的:

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

注意:如JanX2所述,第二种方法对unicode字符串不安全。


5
是的 现在,在必要时,我将继续桥接到NSString。斯威夫特的琴弦似乎仍然不完整
Connor 2014年

14
这不安全!您假设String和NSString的索引可以互换。事实并非如此。字符串的索引引用Unicode代码点,而NSString的索引引用UTF-16代码单元!尝试使用表情符号。
2014年

3
请注意,字符串索引不再引用Unicode代码点。将它们视为引用用户感知的字符。
2014年

2
那么,这里的正确答案是什么?调用advance意味着我们必须遍历整个可能较长的字符串。但是形成一个NSRange并显式地使用NSString是危险的吗?还剩下什么?
马特2014年

1
谢谢,m8。仅使用Objective-C 4年后,这种向Swift的过渡有点混乱。
费利佩

162

迅捷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"

2
这个。如此令人困惑,您必须先找到索引才能使用它。不知道为什么我花了这么长时间才意识到,但感谢您对人类的贡献。
Warpzit

1
在Swift 4中,子字符串操作返回的是Substring类型的实例,而不是String。需要将结果转换为String以便长期存储。让newString = String(substring)
phnmnn

43

注意:@airspeedswift 在此方法的权衡方面提出了一些非常有见地的观点,尤其是对性能的隐性影响。字符串不是简单的野兽,获取特定索引可能需要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)

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


2
出于性能原因,我们应该尽可能多地使用String.Index而不是整数索引。从整数索引到String.Index的每次转换都需要处理要查找的字符串。
2014年

11
@AndrewDunn这不是过早的优化。从整数索引到String.Index的每次转换都是O(n),而不是O(1)!为请阅读评论advance<T>(…)Swift命名空间。
2014年

1
整个String实现都是使用来完成的String.Index。在这种情况下,优化不如保持一切简单明了。不得不在int和String.Index之间四处游荡,这将导致混乱。
chakrit 2014年

@chakrit仅当您需要使用的索引还不是整数(而不是String.Indexes)时(通常是这种情况)。比您只希望所有这些字符串处理方法都可以使用Ints。并且您不得不将其转换String.Indexes为导致您提到的混乱的地方。
拉斯托

感兴趣的读者可以看看ExSwift github.com/pNre/ExSwift
AsTeR 2014年

42

在撰写本文时,没有任何扩展与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

2
@Suragch它处理就OK了:"Hello😇😍😘😎📸📀💾∝ℵℶ≹".substring(from: 4, to: 14)给我们:o😇😍😘😎📸📀💾∝ℵℶ
御寒

但是,这些看起来像普通字符。尝试使用表情符号,例如👩‍👩‍👧‍👦或🇨🇦🇺🇸🇲🇽–
Supuhstar

31

SWIFT 2.0

简单:

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

SWIFT 3.0

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

SWIFT 4.0

子字符串操作返回一个子字符串类型的实例,而不是字符串。

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)

4
不幸的是,自Xcode 8 beta 6起,它不再与Swift 3兼容
Ben Morrow

1
为我工作。Xcode 8,Swift3。在Mac OS Sierra上不是beta。text[text.startIndex..<text.index(text.startIndex, offsetBy: 2)]
何塞·拉米雷斯

18

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

我想带走[和]

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语法有所变化!

请看这个


是的,我也遇到了相同的问题,调试器多次未显示正确的字符串?
user1700737 2014年

我有一个像这样的字符串/ Date(147410000000)/。我如何获得价值而不是指定指数。我需要使用rangeOfString(“(”)和rangeOfString(“)”)获得值。结果应该是147410000000。Ho头我可以得到
iPhone Guy

那不是那么难:var str =“ / Date(147410000000)/”。var range = str.rangeOfString(“(”)!. endIndex .. <str.rangeOfString(“)”)!. startIndex让myNewString = str.substringWithRange(range)
user1700737 2014年

4
由于Xcode 7 beta 6 advance(myString.endIndex, -1)语法已更改为myString.endIndex.advancedBy(-1)
l --marc l

16

例如,以我的全名查找名字(最多第一个空格):

let name = "Joris Kluivers"

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

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

startendString.Index此处的类型,用于创建Range<String.Index>和在下标访问器中使用(如果在原始字符串中根本找不到空格)。

String.Index像在开始文章中所使用的那样,很难直接从整数位置创建一个。这是因为以我的名字,每个字符的大小均以字节为单位。但是在其他语言中使用特殊重音符号的字符可能会再使用几个字节(取决于所使用的编码)。那么整数应该指向哪个字节?

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


16

由于String是NSString的桥接类型,因此“旧”方法应该有效,但尚不清楚如何-例如,这也不起作用(似乎不是有效的语法):

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

对我来说,这是您的问题中真正有趣的部分。字符串桥接到的NSString,所以大多数的NSString方法直接在一根绳子上的工作。您可以自由使用它们而无需考虑。因此,例如,这可以按您期望的那样工作:

// 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))

请注意,此处不涉及任何重大额外工作。“发布”并不意味着“转换”;该字符串实际上是一个NSString。我们只是在告诉Swift如何针对这一行代码查看该变量。

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


但是,我建议提交一个错误。苹果公司应该“诱饵或砍下鱼饵”-要么给我们一种构建的方法,要么让我们Range<String.Index>摆脱这种未记录的方法。
马特2014年

该死的-这很有用。尽管文档说了什么,但直到我读了这篇文章,我才明白出了什么问题。现在已排序:)
Jon M

13

在新的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:

在此处输入图片说明


2
.advancedBy(0) 对于startIndex而言不是必需的。
Mat0

12

简短的答案是,在Swift中,这确实很难。我的直觉是,对于此类事情,苹果仍需要大量工作来研究便捷方法。

String.substringWithRange()我期望有一个Range<String.Index>参数,据我所知,该String.Index类型没有生成器方法。您可以String.IndexaString.startIndex和取回值,aString.endIndex然后调用.succ()或调用.pred()它们,但这很疯狂。

字符串类的扩展采用旧Ints怎么样?

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
️
⃣

1
奇怪的是,核心Swift类似乎只是缺少许多基本功能。我想苹果公司不希望我们不断引用Foundation类来执行简单的任务。
bluedevil2k 2014年

1
完全。请记住,Swift基本上是在黑暗中开发的,每个人对“简单任务”都有不同的定义-我敢打赌,我们在这些问题上看到了一些快速迭代。
Nate Cook

@ JanX2-谢谢,您完全正确。与NSString我之间的无缝桥接使我觉得我只在使用Swift本机String方法,因为我没有使用任何myString as NSString调用。
Nate Cook

Swift-native字符串处理中现在也存在一些Unicode错误:请参阅最后的说明。
Nate Cook

@NateCook您能否为此问题提起雷达?
2014年

11

您可以使用此扩展程序进行改进 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

7

如何在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

希望对您有所帮助!


7

只需少量代码即可轻松解决。

进行扩展,包括几乎所有其他语言都具有的基本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)

1
“ end”参数在这里实际上是指长度,因此我认为应该将其重命名。
Jovan Jovanovski

我认为使用长度相当令人困惑。实际上,这是您希望subString所在的位置的“末端”,而不是subStrings结果的实际长度。
奥利弗·迪克森

6

这在我的操场上工作:)

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

实际上,这比打电话更有效advance
Erik Aigner

2
它在我的Xcode 7(Swift 2)游乐场中不起作用,但这确实...'var str =“你好,游乐场”'String(Array(str.characters)[7])//“ p” String(Array( str.characters)[7 ... 10])//“播放”字符串(Array(str.characters)[7 .. <10])//“ pla”
文斯·奥沙利文

6

已针对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)
        }
    }

}

4

在操场上试试

var str:String = "Hello, playground"

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

它会给你你好,p”

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

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

您还必须给它一个您在操场上感兴趣的实际字符串,因为它似乎使所有的s都一个接一个地保持住,然后是它们的变量名。

所以

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))

给出“你好,操场。str。我是下一个字符串。str2。”

即使str2是用let定义的

:)


我同意,与Objective-C相比,它比较冗长,但是所有内容都适合一行,这是一个额外的好处。
彼得·罗伯茨

在给定计算范围的情况下,仍然缺少一行实际打印出子字符串的代码。我喜欢使用您的逻辑创建String类扩展的其他一些解决方案,但是在扩展中。最终,这就是我所采用的解决方案。
Roderic Campbell 2014年

他们修复了可以超出字符串末尾的错误。现在您只能输入一个值直到str.endIndex
Peter Roberts

4

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 string = str[0...5]
{
    //Manipulate your string safely
}

您那里有一个错误-endIndex应该是startIndex单独由endIndex进行的提前,而不是索引之间的距离。
Aviad Ben Dov

3

Swift3中

例如:变量“ 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)

2

在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>感谢类型推断。
Dan Rosenstark 2014年

2

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

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的答案)。


2

我试图提出一些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!!

1

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

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

1

这是一个从整个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)

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

完整样本,您可以在这里看到



0

好吧,我遇到了同样的问题,并使用“ 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,是为我工作的唯一的事
罗德里克·坎贝尔

0

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

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

0

如果您有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)
}

0

简单扩展String

extension String {

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

0

如果您不关心性能...这可能是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"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.