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

Rob*_*Rob 258 swift

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

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

我无法在Swift中创建一个Range.游乐场中的自动填充功能并不是非常有用 - 这就是它的建议:

return str.substringWithRange(aRange: Range<String.Index>)
Run Code Online (Sandbox Code Playgroud)

我没有在Swift标准参考库中找到任何有帮助的内容.这是另一个疯狂的猜测:

return str.substringWithRange(Range(0, 1))
Run Code Online (Sandbox Code Playgroud)

还有这个:

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

我已经看到其他答案(查找Swift字符串中的字符索引)似乎表明,因为它String是一种桥接类型NSString,"旧"方法应该有效,但是不清楚如何 - 例如,这也不起作用(似乎不是有效的语法):

let x = str.substringWithRange(NSMakeRange(0, 3))
Run Code Online (Sandbox Code Playgroud)

思考?

Con*_*nor 252

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

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

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

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

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

let myNSString = str as NSString
myNSString.substringWithRange(NSRange(location: 0, length: 3))
Run Code Online (Sandbox Code Playgroud)

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

  • 这不安全!您假设String和NSString中的索引是可互换的.事实并非如此.索引到字符串是指Unicode代码点,而索引到NSString是指UTF-16代码单元!用表情符号试试吧. (14认同)
  • 是啊.现在,我会在必要时继续与NSString进行桥接.似乎Swift的String仍然不完整 (5认同)
  • 请注意,String中的索引不再引用Unicode代码点.将它们视为引用用户感知的角色. (3认同)
  • 那么这里的答案是正确的?调用"advance"意味着我们必须遍历可能很长的字符串.但是形成NSRange并明确使用NSString是危险的吗?还剩什么? (2认同)

War*_*shi 161

斯威夫特2

简单

let str = "My String"
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)]
//"Strin"
Run Code Online (Sandbox Code Playgroud)

斯威夫特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"
Run Code Online (Sandbox Code Playgroud)

斯威夫特4

substring(to:)并且substring(from:)已弃用Swift 4.

String(str[..<startIndex])    // "My "
String(str[startIndex...])    // "String"
String(str[startIndex...endIndex])    // "Strin"
Run Code Online (Sandbox Code Playgroud)

  • 这个.令人困惑的是,您必须先找到索引才能使用它.不知道为什么我花了这么长时间才意识到,但感谢你对人类的贡献. (2认同)

Rob*_*ier 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"
Run Code Online (Sandbox Code Playgroud)

(这绝对应该是语言的一部分.请填写: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)
Run Code Online (Sandbox Code Playgroud)

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

  • @AndrewDunn这不是过早的优化.从整数索引到String.Index的每次转换都是O(n),而不是O(1)!请阅读`Swift`命名空间中的'advance <T>(...)`的注释. (11认同)
  • 出于性能原因,我们应尽可能使用String.Index而不是整数索引.从整数索引到String.Index的每次转换都需要处理要搜索的字符串. (2认同)

win*_*zed 41

在我写作的时候,没有任何扩展与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)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用:

let string = "Hello,World!"
Run Code Online (Sandbox Code Playgroud)

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它处理它OK:`"Helloαℵℶ≹".substring(from:4,to:14)`给我们:`oαℵℶ` (2认同)

phn*_*mnn 31

SWIFT 2.0

简单:

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

SWIFT 3.0

let substring = myString[myString.startIndex..<myString.index(myString.startIndex, offsetBy: 3)] // prints: ful
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,从Xcode 8 beta 6开始,不再与Swift 3兼容 (4认同)

use*_*737 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 )
Run Code Online (Sandbox Code Playgroud)

结果将是"ABCDEFGHI",startIndex和endIndex也可用于

let mySubString = myString.substringFromIndex(startIndex)
Run Code Online (Sandbox Code Playgroud)

等等!

PS:正如备注中所示,swift 2中有一些语法更改,包括xcode 7和iOS9!

请看这个页面

  • 自的Xcode 7测试6`提前(myString.endIndex,-1)`语法已更改为`myString.endIndex.advancedBy(-1)` (4认同)

Jor*_*ers 16

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

let name = "Joris Kluivers"

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

if end {
    let firstName = name[start..end!]
} else {
    // no space found
}
Run Code Online (Sandbox Code Playgroud)

start并且endString.Index这里是类型Range<String.Index>,用于在下标访问器中创建和使用(如果在原始字符串中找到空格).

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

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


mat*_*att 16

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

 let x = str.substringWithRange(NSMakeRange(0, 3))
Run Code Online (Sandbox Code Playgroud)

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

// delete all spaces from Swift String stateName
stateName = stateName.stringByReplacingOccurrencesOfString(" ", withString:"")
Run Code Online (Sandbox Code Playgroud)

但是,正如经常发生的那样,"我得到了我的魔力,但它对你不起作用." 你碰巧选择了一种罕见的情况,其中存在一个并行的同名Swift方法,在这种情况下,Swift方法掩盖了Objective-C方法.因此,当你说str.substringWithRange,Swift认为你的意思是Swift方法而不是NSString方法 - 然后你就被软管了,因为Swift方法需要一个Range<String.Index>,而你不知道如何制作其中一个.

最简单的方法是通过显式转换来阻止Swift像这样黯然失色:

let x = (str as NSString).substringWithRange(NSMakeRange(0, 3))
Run Code Online (Sandbox Code Playgroud)

请注意,此处不涉及重要的额外工作."演员"并不意味着"转换"; String 实际上是一个NSString.我们只是告诉Swift如何在这一行代码中查看此变量.

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


Cla*_*nas 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:
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • startIndex不需要`.advancedBy(0)`。 (2认同)

Nat*_*ook 12

简短的回答是,现在Swift真的很难.我的预感是苹果仍然有很多工作要做方便的方法来做这样的事情.

String.substringWithRange()期待一个Range<String.Index>参数,据我所知,该String.Index类型没有生成器方法.你可以String.Index从它们那里得到价值,aString.startIndex然后aString.endIndex再打电话.succ()或者打电话.pred()给他们,但这很疯狂.

如果String类上的扩展需要很好的旧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))   // 
Run Code Online (Sandbox Code Playgroud)

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

由于它处于[beta 3及更早版本],即使是Swift本地字符串也存在处理Unicode字符的一些问题.上面的狗图标工作,但以下不是:

let harderString = "1:1??"
for character in harderString {
    println(character)
}
Run Code Online (Sandbox Code Playgroud)

输出:

1
:
1
?
?
Run Code Online (Sandbox Code Playgroud)


Chi*_*buZ 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特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)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let str = "Hello, playground"

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


Uma*_*ari 7

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

(i)起始索引的子串

输入: -

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

str = str.substringToIndex(str.startIndex.advancedBy(5))
print(str)
Run Code Online (Sandbox Code Playgroud)

输出: -

Swift is very powerful language!
Swift
Run Code Online (Sandbox Code Playgroud)

(ii)来自特定指数的子串

输入: -

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

str = str.substringFromIndex(str.startIndex.advancedBy(6)).substringToIndex(str.startIndex.advancedBy(2))
print(str)
Run Code Online (Sandbox Code Playgroud)

输出: -

Swift is very powerful language!
is
Run Code Online (Sandbox Code Playgroud)

我希望它会对你有所帮助!


Oli*_*xon 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

简单地称之为

someString.subString(start: 0, end: 6)
Run Code Online (Sandbox Code Playgroud)


小智 6

这适用于我的操场:)

String(seq: Array(str)[2...4])
Run Code Online (Sandbox Code Playgroud)

  • 它不适用于我的Xcode 7(Swift 2)游乐场,但这确实......'var str ="Hello,playground"'String(Array(str.characters)[7])//"p"String(Array( str.characters)[7 ... 10])//"play"String(Array(str.characters)[7 .. <10])//"pla" (2认同)

Fir*_*iro 6

更新了Xcode 7.添加字符串扩展名:

使用:

var chuck: String = "Hello Chuck Norris"
chuck[6...11] // => Chuck
Run Code Online (Sandbox Code Playgroud)

执行:

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

}
Run Code Online (Sandbox Code Playgroud)