我想学习将字符串转换为另一个字符串的最佳/最简单的方法,但只有一个子集,从头开始并转到字符的最后一个索引.
例如,将"www.stackoverflow.com"转换为"www.stackoverflow".什么代码片段可以做到这一点,并且是最快速的?(我希望这不会带来争论,但我找不到关于如何处理Swift中的子串的好教训.
fpg*_*503 195
最好的方法是substringToIndex结合使用endIndex属性和advance全局函数.
var string1 = "www.stackoverflow.com"
var index1 = advance(string1.endIndex, -4)
var substring1 = string1.substringToIndex(index1)
Run Code Online (Sandbox Code Playgroud)
使用rangeOfString并设置options为.BackwardsSearch
var string2 = "www.stackoverflow.com"
var index2 = string2.rangeOfString(".", options: .BackwardsSearch)?.startIndex
var substring2 = string2.substringToIndex(index2!)
Run Code Online (Sandbox Code Playgroud)
没有扩展,纯粹惯用的Swift
advance现在是一部分,Index被称为advancedBy.你这样做:
var string1 = "www.stackoverflow.com"
var index1 = string1.endIndex.advancedBy(-4)
var substring1 = string1.substringToIndex(index1)
Run Code Online (Sandbox Code Playgroud)
你不能调用advancedBya,String因为它有可变大小的元素.你必须使用index(_, offsetBy:).
var string1 = "www.stackoverflow.com"
var index1 = string1.index(string1.endIndex, offsetBy: -4)
var substring1 = string1.substring(to: index1)
Run Code Online (Sandbox Code Playgroud)
很多东西都被重命名了.这些案例是用camelCase编写的,startIndex成了lowerBound.
var string2 = "www.stackoverflow.com"
var index2 = string2.range(of: ".", options: .backwards)?.lowerBound
var substring2 = string2.substring(to: index2!)
Run Code Online (Sandbox Code Playgroud)
另外,我不建议强行展开index2.您可以使用可选的绑定或map.就个人而言,我更喜欢使用map:
var substring3 = index2.map(string2.substring(to:))
Run Code Online (Sandbox Code Playgroud)
Swift 3版本仍然有效,但现在您可以使用索引范围的下标:
let string1 = "www.stackoverflow.com"
let index1 = string1.index(string1.endIndex, offsetBy: -4)
let substring1 = string1[..<index1]
Run Code Online (Sandbox Code Playgroud)
第二种方法保持不变:
let string2 = "www.stackoverflow.com"
let index2 = string2.range(of: ".", options: .backwards)?.lowerBound
let substring3 = index2.map(string2.substring(to:))
Run Code Online (Sandbox Code Playgroud)
ser*_*zhd 24
func lastIndexOfCharacter(_ c: Character) -> Int? {
return range(of: String(c), options: .backwards)?.lowerBound.encodedOffset
}
Run Code Online (Sandbox Code Playgroud)
自从advancedBy(Int)Swift 3使用String的方法以来就消失了index(String.Index, Int).String使用substring和friends 查看此扩展:
public extension String {
//right is the first encountered string after left
func between(_ left: String, _ right: String) -> String? {
guard let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
, leftRange.upperBound <= rightRange.lowerBound
else { return nil }
let sub = self.substring(from: leftRange.upperBound)
let closestToLeftRange = sub.range(of: right)!
return sub.substring(to: closestToLeftRange.lowerBound)
}
var length: Int {
get {
return self.characters.count
}
}
func substring(to : Int) -> String {
let toIndex = self.index(self.startIndex, offsetBy: to)
return self.substring(to: toIndex)
}
func substring(from : Int) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: from)
return self.substring(from: fromIndex)
}
func substring(_ r: Range<Int>) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
return self.substring(with: Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex)))
}
func character(_ at: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: at)]
}
func lastIndexOfCharacter(_ c: Character) -> Int? {
return range(of: String(c), options: .backwards)?.lowerBound.encodedOffset
}
}
Run Code Online (Sandbox Code Playgroud)
public extension String {
//right is the first encountered string after left
func between(_ left: String, _ right: String) -> String? {
guard
let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
, leftRange.upperBound <= rightRange.lowerBound
else { return nil }
let sub = self[leftRange.upperBound...]
let closestToLeftRange = sub.range(of: right)!
return String(sub[..<closestToLeftRange.lowerBound])
}
var length: Int {
get {
return self.count
}
}
func substring(to : Int) -> String {
let toIndex = self.index(self.startIndex, offsetBy: to)
return String(self[...toIndex])
}
func substring(from : Int) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: from)
return String(self[fromIndex...])
}
func substring(_ r: Range<Int>) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
let indexRange = Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex))
return String(self[indexRange])
}
func character(_ at: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: at)]
}
func lastIndexOfCharacter(_ c: Character) -> Int? {
return range(of: String(c), options: .backwards)?.lowerBound.encodedOffset
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
let text = "www.stackoverflow.com"
let at = text.character(3) // .
let range = text.substring(0..<3) // www
let from = text.substring(from: 4) // stackoverflow.com
let to = text.substring(to: 16) // www.stackoverflow
let between = text.between(".", ".") // stackoverflow
let substringToLastIndexOfChar = text.lastIndexOfCharacter(".") // 17
Run Code Online (Sandbox Code Playgroud)
PS真的很奇怪,开发商不得不处理String.Index而不是简单Int.我们为什么要打扰内部String机制,而不仅仅是简单的substring()方法?
Mar*_*rný 14
我会使用下标(s[start..<end]):
let s = "www.stackoverflow.com"
let start = s.startIndex
let end = s.index(s.endIndex, offsetBy: -4)
let substring = s[start..<end] // www.stackoverflow
Run Code Online (Sandbox Code Playgroud)
let s = "www.stackoverflow.com"
let start = s.startIndex
let end = s.index(s.endIndex, offsetBy: -4)
let substring = s[start..<end] // www.stackoverflow
Run Code Online (Sandbox Code Playgroud)
例如,将"www.stackoverflow.com"转换为"www.stackoverflow".什么代码片段可以做到这一点,并且是最快速的?
可以更像Swift吗?
let string = "www.stackoverflow.com".stringByDeletingPathExtension // "www.stackoverflow"
Run Code Online (Sandbox Code Playgroud)
更新:Xcode 7.2.1•Swift 2.1.1
extension String {
var nsValue: NSString {
return self
}
}
let string = "www.stackoverflow.com".nsValue.stringByDeletingPathExtension // "www.stackoverflow"
Run Code Online (Sandbox Code Playgroud)
编辑/更新:
在Swift 4或更高版本(Xcode 10.0+)中,您可以使用新的Array lastIndex(of :)
func lastIndex(of element: Element) -> Int?
Run Code Online (Sandbox Code Playgroud)
let string = "www.stackoverflow.com"
if let lastIndex = string.lastIndex(of: ".") {
let subString = string[..<lastIndex] // "www.stackoverflow"
}
Run Code Online (Sandbox Code Playgroud)
这是我如何做到的.您可以以相同的方式执行此操作,也可以将此代码用于创意.
let s = "www.stackoverflow.com"
s.substringWithRange(0..<s.lastIndexOf("."))
Run Code Online (Sandbox Code Playgroud)
以下是我使用的扩展:
import Foundation
extension String {
var length: Int {
get {
return countElements(self)
}
}
func indexOf(target: String) -> Int {
var range = self.rangeOfString(target)
if let range = range {
return distance(self.startIndex, range.startIndex)
} else {
return -1
}
}
func indexOf(target: String, startIndex: Int) -> Int {
var startRange = advance(self.startIndex, startIndex)
var range = self.rangeOfString(target, options: NSStringCompareOptions.LiteralSearch, range: Range<String.Index>(start: startRange, end: self.endIndex))
if let range = range {
return distance(self.startIndex, range.startIndex)
} else {
return -1
}
}
func lastIndexOf(target: String) -> Int {
var index = -1
var stepIndex = self.indexOf(target)
while stepIndex > -1 {
index = stepIndex
if stepIndex + target.length < self.length {
stepIndex = indexOf(target, startIndex: stepIndex + target.length)
} else {
stepIndex = -1
}
}
return index
}
func substringWithRange(range:Range<Int>) -> String {
let start = advance(self.startIndex, range.startIndex)
let end = advance(self.startIndex, range.endIndex)
return self.substringWithRange(start..<end)
}
}
Run Code Online (Sandbox Code Playgroud)
信用albertbori/Common Swift字符串扩展
一般来说,我是扩展的强烈支持者,特别是对于字符串操作,搜索和切片等需求.
String 具有内置子字符串功能:
extension String : Sliceable {
subscript (subRange: Range<String.Index>) -> String { get }
}
Run Code Online (Sandbox Code Playgroud)
如果您想要的是“转到字符的第一个索引”,则可以使用内置find()函数获取子字符串:
var str = "www.stackexchange.com"
str[str.startIndex ..< find(str, ".")!] // -> "www"
Run Code Online (Sandbox Code Playgroud)
要找到最后一个索引,我们可以实现findLast().
/// Returns the last index where `value` appears in `domain` or `nil` if
/// `value` is not found.
///
/// Complexity: O(\ `countElements(domain)`\ )
func findLast<C: CollectionType where C.Generator.Element: Equatable>(domain: C, value: C.Generator.Element) -> C.Index? {
var last:C.Index? = nil
for i in domain.startIndex..<domain.endIndex {
if domain[i] == value {
last = i
}
}
return last
}
let str = "www.stackexchange.com"
let substring = map(findLast(str, ".")) { str[str.startIndex ..< $0] } // as String?
// if "." is found, substring has some, otherwise `nil`
Run Code Online (Sandbox Code Playgroud)
添加:
也许,BidirectionalIndexType专业版findLast更快:
func findLast<C: CollectionType where C.Generator.Element: Equatable, C.Index: BidirectionalIndexType>(domain: C, value: C.Generator.Element) -> C.Index? {
for i in lazy(domain.startIndex ..< domain.endIndex).reverse() {
if domain[i] == value {
return i
}
}
return nil
}
Run Code Online (Sandbox Code Playgroud)
您可以使用这些扩展:
斯威夫特 2.3
extension String
{
func substringFromIndex(index: Int) -> String
{
if (index < 0 || index > self.characters.count)
{
print("index \(index) out of bounds")
return ""
}
return self.substringFromIndex(self.startIndex.advancedBy(index))
}
func substringToIndex(index: Int) -> String
{
if (index < 0 || index > self.characters.count)
{
print("index \(index) out of bounds")
return ""
}
return self.substringToIndex(self.startIndex.advancedBy(index))
}
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(from index: Int) -> String
{
if (index < 0 || index > self.characters.count)
{
print("index \(index) out of bounds")
return ""
}
return self.substring(from: self.characters.index(self.startIndex, offsetBy: index))
}
func substring(to index: Int) -> String
{
if (index < 0 || index > self.characters.count)
{
print("index \(index) out of bounds")
return ""
}
return self.substring(to: self.characters.index(self.startIndex, offsetBy: index))
}
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 string = "www.stackoverflow.com"
let substring = string.substringToIndex(string.characters.count-4)
Run Code Online (Sandbox Code Playgroud)
斯威夫特 4:
extension String {
/// the length of the string
var length: Int {
return self.characters.count
}
/// Get substring, e.g. "ABCDE".substring(index: 2, length: 3) -> "CDE"
///
/// - parameter index: the start index
/// - parameter length: the length of the substring
///
/// - returns: the substring
public func substring(index: Int, length: Int) -> String {
if self.length <= index {
return ""
}
let leftIndex = self.index(self.startIndex, offsetBy: index)
if self.length <= index + length {
return self.substring(from: leftIndex)
}
let rightIndex = self.index(self.endIndex, offsetBy: -(self.length - index - length))
return self.substring(with: leftIndex..<rightIndex)
}
/// Get substring, e.g. -> "ABCDE".substring(left: 0, right: 2) -> "ABC"
///
/// - parameter left: the start index
/// - parameter right: the end index
///
/// - returns: the substring
public func substring(left: Int, right: Int) -> String {
if length <= left {
return ""
}
let leftIndex = self.index(self.startIndex, offsetBy: left)
if length <= right {
return self.substring(from: leftIndex)
}
else {
let rightIndex = self.index(self.endIndex, offsetBy: -self.length + right + 1)
return self.substring(with: leftIndex..<rightIndex)
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以按如下方式进行测试:
print("test: " + String("ABCDE".substring(index: 2, length: 3) == "CDE"))
print("test: " + String("ABCDE".substring(index: 0, length: 3) == "ABC"))
print("test: " + String("ABCDE".substring(index: 2, length: 1000) == "CDE"))
print("test: " + String("ABCDE".substring(left: 0, right: 2) == "ABC"))
print("test: " + String("ABCDE".substring(left: 1, right: 3) == "BCD"))
print("test: " + String("ABCDE".substring(left: 3, right: 1000) == "DE"))
Run Code Online (Sandbox Code Playgroud)
检查https://gitlab.com/seriyvolk83/SwiftEx库。它包含这些和其他有用的方法。
增加咔嗒声的一件事是重复 stringVar:
stringVar [ stringVar .index( stringVar .startIndex, offsetBy: ...)
在斯威夫特 4
扩展可以减少其中的一些:
extension String {
func index(at location: Int) -> String.Index {
return self.index(self.startIndex, offsetBy: location)
}
}
Run Code Online (Sandbox Code Playgroud)
然后,用法:
let string = "abcde"
let to = string[..<string.index(at: 3)] // abc
let from = string[string.index(at: 3)...] // de
Run Code Online (Sandbox Code Playgroud)
需要注意的是to和from是类型Substring(或String.SubSequance)。它们不分配新字符串并且处理效率更高。
要取回String类型,Substring需要将其强制转换为String:
let backToString = String(from)
Run Code Online (Sandbox Code Playgroud)
这是最终分配字符串的地方。
你想得到一个字符串的子串,从起始索引到它的一个字符的最后一个索引吗?如果是这样,您可以选择以下 Swift 2.0+ 方法之一。
Foundation获取包含字符的最后一个索引的子字符串:
import Foundation
let string = "www.stackoverflow.com"
if let rangeOfIndex = string.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "."), options: .BackwardsSearch) {
print(string.substringToIndex(rangeOfIndex.endIndex))
}
// prints "www.stackoverflow."
Run Code Online (Sandbox Code Playgroud)
获取不包含字符的最后一个索引的子字符串:
import Foundation
let string = "www.stackoverflow.com"
if let rangeOfIndex = string.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "."), options: .BackwardsSearch) {
print(string.substringToIndex(rangeOfIndex.startIndex))
}
// prints "www.stackoverflow"
Run Code Online (Sandbox Code Playgroud)
如果您需要重复这些操作,扩展String可能是一个很好的解决方案:
import Foundation
extension String {
func substringWithLastInstanceOf(character: Character) -> String? {
if let rangeOfIndex = rangeOfCharacterFromSet(NSCharacterSet(charactersInString: String(character)), options: .BackwardsSearch) {
return self.substringToIndex(rangeOfIndex.endIndex)
}
return nil
}
func substringWithoutLastInstanceOf(character: Character) -> String? {
if let rangeOfIndex = rangeOfCharacterFromSet(NSCharacterSet(charactersInString: String(character)), options: .BackwardsSearch) {
return self.substringToIndex(rangeOfIndex.startIndex)
}
return nil
}
}
print("www.stackoverflow.com".substringWithLastInstanceOf("."))
print("www.stackoverflow.com".substringWithoutLastInstanceOf("."))
/*
prints:
Optional("www.stackoverflow.")
Optional("www.stackoverflow")
*/
Run Code Online (Sandbox Code Playgroud)
Foundation获取包含字符的最后一个索引的子字符串:
let string = "www.stackoverflow.com"
if let reverseIndex = string.characters.reverse().indexOf(".") {
print(string[string.startIndex ..< reverseIndex.base])
}
// prints "www.stackoverflow."
Run Code Online (Sandbox Code Playgroud)
获取不包含字符的最后一个索引的子字符串:
let string = "www.stackoverflow.com"
if let reverseIndex = string.characters.reverse().indexOf(".") {
print(string[string.startIndex ..< reverseIndex.base.advancedBy(-1)])
}
// prints "www.stackoverflow"
Run Code Online (Sandbox Code Playgroud)
如果您需要重复这些操作,扩展String可能是一个很好的解决方案:
extension String {
func substringWithLastInstanceOf(character: Character) -> String? {
if let reverseIndex = characters.reverse().indexOf(".") {
return self[self.startIndex ..< reverseIndex.base]
}
return nil
}
func substringWithoutLastInstanceOf(character: Character) -> String? {
if let reverseIndex = characters.reverse().indexOf(".") {
return self[self.startIndex ..< reverseIndex.base.advancedBy(-1)]
}
return nil
}
}
print("www.stackoverflow.com".substringWithLastInstanceOf("."))
print("www.stackoverflow.com".substringWithoutLastInstanceOf("."))
/*
prints:
Optional("www.stackoverflow.")
Optional("www.stackoverflow")
*/
Run Code Online (Sandbox Code Playgroud)
如果您知道索引,这里有一个简单而简短的方法来获取子字符串:
let s = "www.stackoverflow.com"
let result = String(s.characters.prefix(17)) // "www.stackoverflow"
Run Code Online (Sandbox Code Playgroud)
如果您的索引超过字符串的长度,它不会使应用程序崩溃:
let s = "short"
let result = String(s.characters.prefix(17)) // "short"
Run Code Online (Sandbox Code Playgroud)
这两个示例都是Swift 3 ready。
| 归档时间: |
|
| 查看次数: |
127591 次 |
| 最近记录: |