2016-09-24 12 views
2

ファイルパスの一部を千のファイルに分割する必要があります。だから、私は速い機能が必要です。私は自分でこれを書いたが、それは非常に遅く実行されるようだ:スイフト3:高速ファイルパス分離

// find string in "str", split at the position, delivers left and right side 

func revFindSplit_(str : String, searchString : String) -> (String, String) { 
    let strr = String(str.characters.reversed()) // reverse main string 
    let searchStringr = String(searchString.characters.reversed()) // reverse search string too 

    if let strrindex = strr.range(of: searchStringr) { // now we can search from back to front 

     let rangeOfS2 = strr.characters.startIndex..<strrindex.lowerBound // we got search result: part 1 (front) 
     let rangeOfS1 = strrindex.lowerBound..<strr.characters.endIndex // part 2 (back) 
     let S2 = String(strr[rangeOfS2].characters.reversed()) // put together and reverse again 
     let S1 = String(strr[rangeOfS1].characters.reversed()) 

     // here we have to remove search string 
     let S1M1 = String(S1.characters.prefix(S1.characters.count - searchString.characters.count)) 

     return (S1M1, S2) 
    } 
    else { 
     return (str, "") // without splitting 
    } 
} 

// split path of filename into all 3 part: directory name, filename without extension, extension (without dot) 
// in one call (faster than the 3 functions separatly) 
func splitFilename_(str: String) -> (directory: String, filenameOnly: String, ext: String) { 
    let url = NSURL(fileURLWithPath: str) 
    let path = url.path! 

    // split path and filename 
    let (directory, filenameExt) = revFindSplit_(str: path, searchString: "/") 
    // split filename in filenameOnly and extension 
    let (filenameOnly, ext) = revFindSplit_(str: filenameExt, searchString: ".") 

    return (directory, filenameOnly, ext) 
} 

それを劇的にスピードアップする方法はありますか? (おそらくライブラリ関数を使用して)

+0

を私は@vardianによるソリューションを使用しているときにパフォーマンスの問題を持っている疑い。しかし、それが本当に速くなく、スピードアップが必要な場合は、文字列 'import Glibc'または' import Darwin'からUTF8を取得し、C関数を使用します( 'basename'、' strstr'等。)。 – hnh

答えて

2

あなたはあなたの全体のコード減らすことができます。

func splitFilename(str: String) -> (directory: String, filenameOnly: String, ext: String) { 
    let url = URL(fileURLWithPath: str) 
    return (url.deletingLastPathComponent().path, url.deletingPathExtension().lastPathComponent, url.pathExtension) 
} 
+0

それは素晴らしいです。まさに私が探し求めたもの。私は今(Swift 3.0で)始めているので、それを正しくやりたい。 :-) どうもありがとうございました。 –

1

数千の文字列を分割することは、現代のCPU標準では大きな仕事ではありません。インテルのCPUを困らせるには、何百万もの人が必要です。そして、これがあなたのアプリケーションのボトルネックだと確信していますか?

「プリ成熟した最適化は、すべての悪の根である」

- ドナルド・クヌース

そして最後に、あなたのコードは叙事詩であります!あなたはNSStringに組み込まれているパス操作を試しましたか?

func splitFileName(str: String) -> (directory: String, fileName: String, extension: String) { 
    let path = str as NSString 
    let directory = path.deletingLastPathComponent 

    let fileNameWithExtension = path.lastPathComponent as NSString 
    let fileNameWithoutExtension = fileNameWithExtension.deletingPathExtension 
    let fileExtension = fileNameWithExtension.pathExtension 

    return (directory, fileNameWithoutExtension, fileExtension) 
} 
+0

Swiftでは 'NSString'の組み込みパス操作が古くなっています。 URLが好ましい。 – vadian

+0

メソッドはまだ 'NSString'にあり、NSStringはすぐに外に出ることはありません –

+1

はい、** Swift(3)**の最先端のクラス(実際には構造体)は' String 'と' URL'です。開発者がURL関連のAPIを使用するように促すために、AppleがSwiftの 'String'でパス操作メソッドを削除したというパフォーマンス上の理由があります。 – vadian