我想找到String中最后一个字符出现的索引。例如,如果我的字符串是"google.com/program/test"
并且我想找到字母/
,我希望我的函数返回18
,因为这是该字符串中/
的最后一次出现。我试图遵循Finding index of character in Swift String并尝试实现循环字符串的方法,只是找到具有我想要的字符的字符串的最后一个索引,但advance()
函数似乎抱怨获取一个整数。
var strCount = 0
var lastSlashIndex = 0
for i in urlAsString {
if i == "/"{
if lastSlashIndex < strCount{
lastSlashIndex = strCount
}
}
strCount++
}
var endOfString = strCount - lastSlash
//Cannot seem to use the advance function to get the remaining substring
var fileName = urlAsString.substringFromIndex(advance(lastSlashIndex, endOfString))
似乎无法弄明白,任何帮助都会受到赞赏。
编辑:
这个问题并不仅限于'/'字符。例如,如果字符串是"abbccd"
并且我正在寻找字母'c'
,那么我想返回索引4
,因为这是'c'
的最后一个索引发生在。
答案 0 :(得分:6)
我没有回答标题中的问题,而是看看你的示例代码并假设这是一个XY问题。如果您只需要删除最后一个路径组件(或仅检索最后一个路径组件),NSString
上的现有方法可以使这很容易。
如果你想要的只是从路径中提取的文件名:
let path = "/tmp/scratch.tiff"
let fileName = path.lastPathComponent
即使path
看起来像某种URL,这也有效。
let path = "https://www.dropbox.com/s/s73824fsda/FileName.ext"
let fileName = path.lastPathComponent
println(fileName)
打印:
FileName.ext
作为一个注释,无论最后一个路径组件是否具有任何类型的扩展或其他什么,这都有效。 lastPathComponent
只返回最后一个/
字符后的所有内容(如果没有/
,则返回整个字符串。)
NSString
实际上明确定义了很多用于处理文件路径的方法(这些方法都适用于Swift的String
)。我建议你看一下official documentation。 NSString
有一整套方法称为“使用路径”
答案 1 :(得分:2)
如果你想找到第一个出现的字符,可以使用find
函数,所以一个选项就是编写一个反向查找等价物,以常规查找为模型,然后使用:< / p>
func rfind
<C: CollectionType
where C.Generator.Element: Equatable,
// one extra constraint needed - the ability
// to iterate backwards through the collection
C.Index: BidirectionalIndexType>
(domain: C, value: C.Generator.Element) -> C.Index? {
// the wrapping of the indices in reverse() is really
// the only difference between this and the regular find
for idx in reverse(indices(domain)) {
if domain[idx] == value {
return idx
}
}
return nil
}
鉴于此,很容易使用它来查找由最后一个字符分隔的子字符串:
let path = "/some/path/to/something"
if let firstSlash = rfind(path, "/") {
let file = path[firstSlash.successor()..<path.endIndex]
println(file) // prints “something”
}
当然,如果您不想在定义泛型函数时遇到麻烦,可以直接在代码中编写循环。
注意,虽然Swift中的字符串不是通过整数进行随机访问,但它并不重要,因为您无需知道最后一个斜杠是第n个字符,只是它的位置索引。
如果你想假设没有斜杠意味着把整个字符串作为你可以做的文件名:
let start = find(path, "/")?.successor() ?? path.startIndex
let file = path[start..<path.endIndex]
答案 2 :(得分:2)
@Duncan C建议使用rangeOfString函数。
以下是Swift 2.0中可能出现的示例:
func lastIndexOf(s: String) -> Int? {
if let r: Range<Index> = self.rangeOfString(s, options: .BackwardsSearch) {
return self.startIndex.distanceTo(r.startIndex)
}
return Optional<Int>()
}
测试
func testStringLastIndexOf() {
let lastIndex = "google.com/program/test".lastIndexOf("/")
XCTAssertEqual(lastIndex, 18)
}
func testStringLastIndexOfNotFound() {
let lastIndex = "google.com".lastIndexOf("/")
XCTAssertEqual(lastIndex, nil);
}
答案 3 :(得分:0)
@nhgrif可能是正确的,这是一个XY问题,你真正想做的是解析一个路径或一个URL,NSString和NSURL中有内置的方法来为你做这个。
如果您正在谈论通用字符串解析,那么也有方法。
到目前为止,最简单的方法是使用NSString方法rangeOfString:options:
其中一个选项值是BackwardsSearch。所以你要传递一个BackwardsSearch的选项值。您将获得搜索字符串最后出现的范围。
我见过一些使用“Swift-ified”版本范围的Swift字符串方法,并且我不清楚NSString方法有什么原生Swift变种。 (我自己也在学习Swift。)
答案 4 :(得分:0)
以下使用您可以选择查找的字符串的扩展程序来完成此任务。如果它不可用,那么你可以得到一个可以处理的零值。
extension String {
func lastOccurrenceOfString(string: String) -> String.Index? {
let characterSet = CharacterSet(charactersIn: string)
if let range = rangeOfCharacter(from: characterSet, options: .backwards) {
let offsetBy = distance(from: startIndex, to: range.upperBound)
return index(startIndex, offsetBy: offsetBy)
}
return nil
}
}
以下显示了这一点:
import UIKit
class ViewController: UIViewController {
let testString = "google.com/program/test"
override func viewDidLoad() {
super.viewDidLoad()
getIndex(of: "/") // 19
getIndex(of: ".") // 7
getIndex(of: "z") // N/A
getIndex(of: "me") // 21, e appears before m
}
func getIndex(of string: String) {
let slashIndex = testString.lastOccurrenceOfString(string: string)
print(slashIndex?.encodedOffset ?? "N/A")
}
}
extension String {
func lastOccurrenceOfString(string: String) -> String.Index? {
let characterSet = CharacterSet(charactersIn: string)
if let range = rangeOfCharacter(from: characterSet, options: .backwards) {
let offsetBy = distance(from: startIndex, to: range.upperBound)
return index(startIndex, offsetBy: offsetBy)
}
return nil
}
}