2016-09-24 1 views
2

Je dois diviser des parties d'un chemin de fichier pour des milliers de fichiers. J'ai donc besoin d'une fonction rapide. J'ai écrit ce par moi-même, mais il semble fonctionner très lent:Swift 3: séparation rapide du chemin de fichier

// 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) 
} 

Est-il possible d'accélérer de façon spectaculaire? (peut-être en utilisant des fonctions de bibliothèque)

+0

Je doute que vous avez un problème de performance lors de l'utilisation de la solution par @vardian. Mais si cela n'est pas assez rapide et que vous avez besoin d'une accélération "dramatique", prenez l'UTF8 de la chaîne, 'import Glibc' ou' import Darwin' et utilisez les fonctions C sur cela (comme 'basename',' strstr' etc.). – hnh

Répondre

2

Vous pouvez réduire votre code entier:

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

C'est excellent. Exactement ce que j'ai cherché. Parce que je commence maintenant (avec Swift 3.0), je veux le faire correctement. :-) Merci beaucoup. –

1

Diviser des milliers de chaînes n'est pas une tâche importante selon la norme CPU actuelle. Pour mettre un processeur Intel en difficulté, vous auriez besoin de millions. Et êtes-vous sûr que c'est le goulot d'étranglement de votre application?

"optimisation pré-mature est la racine de tous les maux" - Donald Knuth

Et enfin, votre code est épique! Avez-vous essayé la manipulation de chemin intégrée à 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

La manipulation de chemin intégrée de 'NSString' est obsolète dans Swift. 'URL' est préférable. – vadian

+0

Les méthodes sont toujours là sur 'NSString' et' NSString' ne partiront pas de sitôt. –

+1

Oui, mais les classes state-of-the-art (en fait les structures) dans ** Swift (3) ** sont 'String 'et' URL'. Il y a une raison de performance pour laquelle Apple a abandonné les méthodes de manipulation de chemins dans Swift 'String' pour encourager les développeurs à utiliser l'API liée à l'URL. – vadian