Swift fast low level String lastIndexOf



我需要尽快实现lastIndexOf。我发现字符串前进功能非常慢。我尝试使用 c 函数 strrchr,并尝试将字符串复制到 NSData 并使用指针,但我无法获得正确的语法。我的字符串将始终具有 1 个字节字符,我正在搜索"|"的字符串也始终为 1 个字节。

任何使用 advance 的实现都会太慢,但这是我能找到的最快的示例:

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
}

这是我需要解析的字符串的示例。 var str:String = "4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|6|0|3259744|6352141|46|14|1|0|7|7|3259744|6352141|4|1|0|8|8|3259744|6352141|4|0|22|9|0|3259744|6352141|2|3|Room1|2|72|86330534|1|0|10|9|3259744|6352141|4|1|0|11|10|3259744|6352141|4|1|0|12|11|3259744|6352141|4|1|0|13|12|3259744|6352141|4|0|4|14|0|3259744|6352141|46|24|0|5|15|0|3259744|6352141|46|654|0|66|0|0|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|16|0|3259744|6352141|46|4sageReceived:4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|6|0|3259744|6352141|46|14|1|0|7|7|3259744|6352141|4|1|0|8|8|3259744|6352141|4|0|22|9|0|3259744|6352141|2|3|Room1|2|72|86330534|1|0|10|9|3259744|6352141|4|1|0|11|10|3259744|6352141|4|1|0|12|11|3259744|6352141|4|1|0|13|12|3259744|6352141|4|0|4|14|0|3259744|6352141|46|24|0|5|15|0|3259744|6352141|46|654|0|66|0|0|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|16|0|3259744|6352141|46|4352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|6|0|3259744|6352141|46|14|1|0|7|7|3259744|6352141|4|1|0|8|8|3259744|6352141|4|0|22|9|0|3259744|6352141|2|3|Room1|2|72|86330534|1|0|10|9|3259744|6352141|4|1|0|11|10|3259744|6352141|4|1|0|12|11|3259744|6352141|4|1|0|13|12|3259744|6352141|4|0|4|14|0|3259744|6352141|46|24|0|5|15|0|3259744|6352141|46|654|0|66|0|0|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|16|0|3259744|6352141|46|4TCPListener.onReceived: 4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|6|0|3259744|6352141|46|14|1|0|7|7|3259744|6352141|4|1|0|8|8|3259744|6352141|4|0|22|9|0|3259744|6352141|2|3|Room1|2|72|86330534|1|0|10|9|3259744|6352141|4|1|0|11|10|3259744|6352141|4|1|0|12|11|3259744|6352141|4|1|0|13|12|3259744|6352141|4|0|4|14|0|3259744|6352141|46|24|0|5|15|0|3259744|6352141|46|654|0|66|0|0|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|16|0|3259744|6352141|46|4preParse4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.221283">

这是一个 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 = "0|2|45|7|9".lastIndexOf("|")
    XCTAssertEqual(lastIndex, 8)
}
func testStringLastIndexOfNotFound() {
    let lastIndex = "0123456789".lastIndexOf("|")
    XCTAssertEqual(lastIndex, nil);
}

你可以在 Swift 中使用 strrchr

import Darwin
let str = "4|0|66|5|0|3259744|6352141|1|3259744"
func stringLastIndexOf(src:String, target:UnicodeScalar) -> Int? {
    let c = Int32(bitPattern: target.value)
    return src.withCString { s -> Int? in
        let pos = strrchr(s, c)
        return pos != nil ? pos - s : nil
    }
}
stringLastIndexOf(str, "|") // -> {Some 28}
stringLastIndexOf(str, ",") // -> nil

你可以在 Swift 项目中使用 Objective C 文件;在这些项目中,你可以使用纯 C 代码并创建一个使用 strrchr 的函数。然后你可以从 Swift 调用它。

如果您这样做是为了获取由"|"分隔的所有子字符串,则可以测试此方法:

import Foundation
let s = "4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|..."
let a = s.componentsSeparatedByString("|")

内置函数有时非常快,即使使用 String 也可能获得所需的性能。

如果你真的只需要获取最后一个"|"的位置,你可以使用 utf16 表示,其中在字符上前进应该更快。

我认为这应该有效:

let utf16String = s.utf16
var i = s.utf16Count - 1
while i >= 0 {
    if utf16String[i] == 124 {
        break
    }
    i--
}
println(i)

如果字符保证为单字节,数据量大且性能至关重要,那么可能值得转换为字节数组 (UInt8( 并直接对它们执行操作。然后,您可以将所需的部分转换回字符串。

另请注意,优化版本

可能比调试版本快得多,因此您应该在启用优化器的情况下进行任何性能测试。可能还值得检查优化版本目前是否太慢。

最新更新