Swift快速低级别字符串lastIndexOf

时间:2014-12-19 17:21:32

标签: string swift c-strings

我需要尽可能快的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 | 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 | 3259744 | 6352141 | 1 | 3259744 | WSMxt208L54y Z5irtHC3 | 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 | 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 | 3259744 | 6352141 | 1 | 3259744 | WSMxt208L54yZ5irtHC3 | MC02 | efland,NC | 36.027992 | -79.2212834 | 0 | 4 | 16 | 0 | 3259744 | 6352141 | 46 | 4preParse 4 | 0 | 66 | 5 | 0 | 3259744 | 6352141 | 1 | 3259744 | WSMxt208L54yZ5irtHC3 | MC02 | efland,NC | 36.027992 | -79.221283"

5 个答案:

答案 0 :(得分:6)

这是一个Swift 2.0答案

null

测试

func lastIndexOf(s: String) -> Int? {
    if let r: Range<Index> = self.rangeOfString(s, options: .BackwardsSearch) {
        return self.startIndex.distanceTo(r.startIndex)
    }

     return Optional<Int>()
}

答案 1 :(得分:4)

您可以在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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

如果你这样做是为了让所有子字符串用“|”分隔,你可以测试这种方法:

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)

答案 4 :(得分:0)

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

另请注意,优化版本可能比Debug版本快得多,因此您应该使用优化器进行任何性能测试。也许值得检查优化版本目前是否太慢。