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.
注意:我找到了一种方法来完成我正在寻找的事情,代码如下。我现在需要尽可能多地优化它,因为在具有 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.