Swift:排序路径的排序函数(要快!)

Swift: sorting function for ordering paths (needs to be fast!)

注意:我找到了一种方法来完成我正在寻找的事情,代码如下。我现在需要尽可能多地优化它,因为在具有 8k 个对象的数组上执行仍然需要 20 秒以上

我想对 Array 个具有 path 属性 并表示用户系统上的文件的对象进行排序。我想要实现的是:

考虑这个目录结构

├── a
│   └── a.ext
├── b
│   ├── b.ext
│   ├── c.ext
│   └── d
│       └── d.ext
├── c
│   └── e.ext
├── f.ext
└── g.ext

当使用 NSFileManager 读取目录内容时,我得到的路径顺序不是我想要的。因此,我需要对数组进行排序以获得顺序:

./f.ext
./g.ext
./a/a.ext
./b/b.ext
./b/c.ext
./b/d/d.ext
./c/e.ext

排序应不区分大小写。对于每个文件夹,首先按字母顺序显示文件,然后显示文件夹,并且在这些文件夹中的每一个中都应用相同的规则。

有没有办法对数组进行排序以获得所需的顺序?排序功能是什么样的?

谢谢!

编辑:

我自己找到了解决方案,但我现在想知道是否可以加快速度?

    func sorter(obj1: FilesListData, obj2: FilesListData) -> Bool {
        var result: Bool = false

        let url1 = NSURL(fileURLWithPath: obj1.path)
        let url2 = NSURL(fileURLWithPath: obj2.path)
        guard let c1 = url1.pathComponents else {
            return result
        }
        guard let c2 = url2.pathComponents else {
            return result
        }

        for i in 0..<min(c1.count, c2.count) {
            if c1[i] == c2[i] {
                continue
            } else {
                if i+1 == c1.count {
                    if i+1 == c2.count {
                        result = c1[i].lowercaseString < c2[i].lowercaseString
                        break
                    } else {
                        result = true
                        break
                    }
                } else {
                    if i+1 == c2.count {
                        result = false
                        break
                    } else {
                        result = c1[i].lowercaseString < c2[i].lowercaseString
                        break
                    }
                }
            }
        }

        return asc ? result : !result //asc is a variable indicating if the order should be ascending or not
    }

这有帮助吗?用法:

printContents("/Users/paulvs/Desktop/my directory")

代码:

func printContents(path: String) {
    let fileManager = NSFileManager()
    let URL = NSURL(fileURLWithPath: path)
    let keys = [NSURLIsDirectoryKey]
    let enumerator = fileManager.enumeratorAtURL(URL, includingPropertiesForKeys: keys, options: NSDirectoryEnumerationOptions(rawValue: 0), errorHandler: { url, error -> Bool in
        return true
    })!

    var filePaths = [String]()
    var directoryPaths = [String]()

    while let url = enumerator.nextObject() as? NSURL {
        var path: AnyObject?
        var isDirectory: AnyObject?
        do {
            try url.getResourceValue(&isDirectory, forKey: NSURLIsDirectoryKey)
            try url.getResourceValue(&path, forKey: NSURLPathKey)

            if isDirectory as? Bool == true {
                directoryPaths.append(path as! String)
                enumerator.skipDescendants()
            } else {
                filePaths.append(path as! String)
            }
        } catch _ {

        }
    }

    filePaths.sort().forEach({ filePath in
        print(filePath)
    })

    directoryPaths.sort().forEach({ directoryPath in
        printContents(directoryPath)
    })
}

因此,您想按最外层目录作为第一个排序键对路径进行排序,然后将下一个内部目录作为第二个排序键,直到文件名作为最后一个排序键(其中任何级别的目录都不会排序到顶部)?

如果混合中只有一个目录,这将非常简单。获取目录。获取文件名。创建一个排序描述符,使用这 2 个作为排序键进行排序。如果您需要处理更深层次的目录结构,它会变得更复杂一些。

这里有一个简洁的方法,我认为应该足够快:

[编辑:调整以显示如何将其与对象列表一起使用]

class FileObject
{
   var path:String
   init(_ path:String)
   { self.path = path }
}

var files:[FileObject] = 
  [
    FileObject("./b/c.ext"),
    FileObject("./f.ext"),
    FileObject("./g.ext"),
    FileObject("./a/a.ext"),
    FileObject("./b/b.ext"),
    FileObject("./b/d/d.ext"),
    FileObject("./c/e.ext")
  ]

files = files.map({ ([=10=], [=10=].path.rangeOfString("/", options: .BackwardsSearch)!) })
             .map({ ([=10=], [=10=].path.stringByReplacingCharactersInRange(, withString: "/ ")) })
             .map({ ([=10=], .lowercaseString) })
             .sort({ [=10=].1 < .1 })
             .map({  [=10=].0 })


files.forEach({ print([=10=].path) })

// prints:
//
// ./f.ext
// ./g.ext
// ./a/a.ext
// ./b/b.ext
// ./b/c.ext
// ./b/d/d.ext
// ./c/e.ext

// Benchmark for 8000 gives 0.134 sec.