Skip to content

Instantly share code, notes, and snippets.

@TimOliver
Created May 4, 2020 13:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TimOliver/8c70605c16b855623fc68ea3ca433b0e to your computer and use it in GitHub Desktop.
Save TimOliver/8c70605c16b855623fc68ea3ca433b0e to your computer and use it in GitHub Desktop.
An algorithm I wrote to sort a list of file paths in varying levels of directories into ascending order
extension String {
/// Compares the current string value as a file path against a second
/// file path string in order to determine which comes first.
///
/// Rules:
/// * Item names are only compared if they are in the same directory
/// * Items in higher parent directories always take priority
/// * Files prefixed with "_" are automatically downgraded (Since files prefixed like that are usually ads)
///
/// - Parameter secondString: The string to compare this string against
/// - Returns: `true` if the ordering is ascending, and `false` otherwise
public func filePathCompare(with secondString: String) -> Bool {
// Format the inputs to remove any possible leading slashes
var firstFilePath = self.deletingPrefix("/")
var secondFilePath = secondString.deletingPrefix("/")
// If one URL has less slashes (ie, the item is in a parent directory), favour that one
let firstFolderCount = firstFilePath.countInstances(of: "/")
let secondFolderCount = secondFilePath.countInstances(of: "/")
if firstFolderCount != secondFolderCount {
return firstFolderCount < secondFolderCount
}
// Loop through until we go past the front of either URL
while firstFilePath.lastPathComponent != ".." && secondFilePath.lastPathComponent != ".." {
// Get the last component of the file path
let firstFileName = firstFilePath.lastPathComponent
let secondFileName = secondFilePath.lastPathComponent
// Remove the components from the file paths
firstFilePath = firstFilePath.deletingLastPathComponent
secondFilePath = secondFilePath.deletingLastPathComponent
// If the truncated file paths don't match, go up one more level until they do
if firstFilePath.compare(secondFilePath) != .orderedSame {
continue
}
// Once the truncated file URLs match, this means the items being compared
// are both in the same directory. We can do a file name compare to determine
// the ordering
// Always give lower priority to files pre-fixed with '_'
if firstFileName.hasPrefix("_") { return false }
if secondFileName.hasPrefix("_") { return true }
// Perform a compare on just the file names
return firstFileName.localizedCompare(secondFileName) == .orderedAscending
}
// Default to ascending (But this should never be called)
return true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment