我还没有弄清楚如何在Swift中获取String
的子字符串:
var str = “Hello, playground”
func test(str: String) -> String {
return str.substringWithRange( /* What goes here? */ )
}
test (str)
我无法在Swift中创建一个Range。游乐场中的自动填充功能并不是非常有用 - 这就是它的建议:
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)似乎暗示,因为String
是NSString
的桥接类型,所以#34;旧的&#34;方法应该有效,但不清楚 - 例如,这也不起作用(看起来不是有效的语法):
let x = str.substringWithRange(NSMakeRange(0, 3))
思想?
答案 0 :(得分:250)
您可以使用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字符串是不安全的。
答案 1 :(得分:160)
简单
let str = "My String"
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)]
//"Strin"
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"
substring(to:)
和substring(from:)
已弃用Swift 4
。
String(str[..<startIndex]) // "My "
String(str[startIndex...]) // "String"
String(str[startIndex...endIndex]) // "Strin"
答案 2 :(得分:43)
注意:@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)
(我不知道这个是否应该成为该语言的一部分。)
答案 3 :(得分:40)
在我写作的时候,没有任何扩展名完全 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)
以支持从零开始。
答案 4 :(得分: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
子串操作返回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)
答案 5 :(得分: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 )
结果将是&#34; ABCDEFGHI&#34;
中也可以使用startIndex和endIndexlet mySubString = myString.substringFromIndex(startIndex)
等等!
PS:如备注中所示,swift 2中有一些语法更改,包括xcode 7和iOS9!
请查看此page
答案 6 :(得分:16)
例如,以我的全名查找名字(直到第一个空格):
let name = "Joris Kluivers"
let start = name.startIndex
let end = find(name, " ")
if end {
let firstName = name[start..end!]
} else {
// no space found
}
start
和end
此处的类型为String.Index
,用于创建Range<String.Index>
并在下标访问器中使用(如果在此处找到空格)原始字符串)。
很难直接从开场帖中使用的整数位置创建String.Index
。这是因为在我的名字中,每个字符的大小都是相等的。但是在其他语言中使用特殊重音的字符可能使用了几个字节(取决于所使用的编码)。那么整数应该引用什么字节?
可以使用方法String.Index
和succ
从现有方法创建新的pred
,这样可以确保跳过正确的字节数编码中的下一个代码点。但是在这种情况下,搜索字符串中第一个空格的索引以查找结束索引更容易。
答案 7 :(得分:15)
由于String是NSString的桥接类型,因此&#34; old&#34;方法应该有效,但不清楚 - 例如,这也不起作用(看起来不是有效的语法):
let x = str.substringWithRange(NSMakeRange(0, 3))
对我而言,这是你问题中非常有趣的部分。 String 桥接到NSString,因此大多数 NSString方法做直接在String上工作。您可以自由地使用它们而无需考虑。因此,例如,这可以像您期望的那样工作:
// delete all spaces from Swift String stateName
stateName = stateName.stringByReplacingOccurrencesOfString(" ", withString:"")
但是,正如经常发生的那样,&#34;我得到了我的魔力。但它只是不适合你。&#34;你碰巧选择了一个罕见的情况,其中存在一个平行的同名Swift方法,在这种情况下,Swift方法掩盖了Objective-C方法。因此,当你说str.substringWithRange
时,Swift认为你的意思是Swift方法而不是NSString方法 - 然后你被软管,因为Swift方法需要一个Range<String.Index>
,你不知道如何制作其中一个。
简单的方法是通过明确地强制转换来阻止Swift像这样黯然失色:
let x = (str as NSString).substringWithRange(NSMakeRange(0, 3))
请注意,此处不涉及任何重要的额外工作。 &#34;演员#34;并不意味着&#34;转换&#34 ;; String 实际上是一个NSString。我们只是告诉Swift如何在此变量中看以达到这一行代码的目的。
整个事情的真正奇怪的部分是导致所有这些麻烦的Swift方法没有记录。我不知道它的定义在哪里;它不在NSString标题中,也不在Swift标题中。
答案 8 :(得分: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:
答案 9 :(得分:12)
简短的回答是,现在Swift真的很难。我的预感是苹果仍然需要做一些方便的方法来处理这类事情。
String.substringWithRange()
期待Range<String.Index>
参数,据我所知,String.Index
类型没有生成器方法。您可以从String.Index
和aString.startIndex
获取aString.endIndex
值,并在其上调用.succ()
或.pred()
,但这很疯狂。
String类的扩展如何使用好的Int
s?
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
️
⃣
答案 10 :(得分:11)
您可以使用此扩展程序来改进substringWithRange
Swift 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)
}
}
Swift 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
答案 11 :(得分:7)
使用少量代码轻松解决问题。
制作一个扩展程序,其中包含几乎所有其他语言都具有的基本子索引:
InnerBase
只需用
调用即可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)
}
}
答案 12 :(得分: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
我希望它会对你有所帮助!
答案 13 :(得分:6)
这适用于我的游乐场:)
String(seq: Array(str)[2...4])
答案 14 :(得分: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)
}
}
}
答案 15 :(得分:4)
在游乐场试试这个
var str:String = "Hello, playground"
let range = Range(start:advance(str.startIndex,1), end: advance(str.startIndex,8))
它会给你&#34; ello,p&#34;
然而,这真的很有趣的是,如果你使最后一个索引大于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))
给&#34; ello,playground�str���I&#39;下一个string�str2�&#34;
即使用let 定义了str2,也能正常工作
:)
答案 16 :(得分: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
if let string = str[0...5]
{
//Manipulate your string safely
}
答案 17 :(得分:3)
在 Swift3
中对于ex:变量&#34; Duke James Thomas&#34;,我们需要得到&#34; James&#34;。
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)
答案 18 :(得分: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"
答案 19 :(得分: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!!
答案 20 :(得分: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's answer)。
答案 21 :(得分:1)
首先创建范围,然后创建子字符串。您可以使用fromIndex..<toIndex
语法,如下所示:
let range = fullString.startIndex..<fullString.startIndex.advancedBy(15) // 15 first characters of the string
let substring = fullString.substringWithRange(range)
答案 22 :(得分:1)
let startIndex = text.startIndex
var range = startIndex.advancedBy(1) ..< text.endIndex.advancedBy(-4)
let substring = text.substringWithRange(range)
完整示例,您可以看到here
答案 23 :(得分:1)
以下是从swift中的整个网址获取仅使用视频ID的示例.i.e(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)
答案 24 :(得分:0)
String
的简单扩展程序:
extension String {
func substringToIndex(index: Int) -> String {
return self[startIndex...startIndex.advancedBy(min(index, characters.count - 1))]
}
}
答案 25 :(得分:0)
http://www.learnswiftonline.com/reference-guides/string-reference-guide-for-swift/ 表明这很有效:
var str = "abcd"
str = str.substringToIndex(1)
答案 26 :(得分: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位置结束(字符“!”)
干杯。
答案 27 :(得分: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)
}
答案 28 :(得分:0)
您可以在我编写https://bit.ly/JString的Swift String扩展中使用任何子字符串方法。
var string = "hello"
var sub = string.substringFrom(3) // or string[3...5]
println(sub)// "lo"
答案 29 :(得分: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"
答案 30 :(得分:-1)
Swift 3.0
我决定对此有一点乐趣并在String
上制作一个扩展名。我可能没有正确使用truncate这个词,因为我实际上已经有了这个功能。
extension String {
func truncate(from initialSpot: Int, withLengthOf endSpot: Int) -> String? {
guard endSpot > initialSpot else { return nil }
guard endSpot + initialSpot <= self.characters.count else { return nil }
let truncated = String(self.characters.dropFirst(initialSpot))
let lastIndex = truncated.index(truncated.startIndex, offsetBy: endSpot)
return truncated.substring(to: lastIndex)
}
}
let favGameOfThronesSong = "Light of the Seven"
let word = favGameOfThronesSong.truncate(from: 1, withLengthOf: 4)
// "ight"
答案 31 :(得分:-1)
Swift 3.X +,Xcode 8.X + 经过测试的简易解决方案;
使用简单;
let myString = "12.12.2017 12:34:45"
let newString = myString?[(myString?.startIndex)!..<(myString?.index((myString?.startIndex)!, offsetBy: 10))!]
print(newString)
产出= 12.12.2017
对于自定义很容易改变;
offsetBy: 10 // Change 10 to endIndex.
当你改变offsetBy:10到15,20等会削减你的字符串..
谢谢!
答案 32 :(得分:-4)
有很多关于如何解决这个问题的好例子。最初的问题是关于使用substringWithRange,但正如已经指出的那样,除了进行自己的扩展之外,还有一个更难的方法。
以上范围的解决方案是好的。您还可以通过其他方式执行此操作。这是您如何做到这一点的另一个例子:
extension String{
func sub(start: Int, length: Int) -> String {
assert(start >= 0, "Cannot extract from a negative starting index")
assert(length >= 0, "Cannot extract a negative length string")
assert(start <= countElements(self) - 1, "cannot start beyond the end")
assert(start + length <= countElements(self), "substring goes past the end of the original")
var a = self.substringFromIndex(start)
var b = a.substringToIndex(length)
return b
}
}
var s = "apple12345"
println(s.sub(6, length: 4))
// prints "2345"