Sometimes lexicographical sorting of strings may cut it, but when browsing the filesystem, you really need better sorting criteria than just ASCII indices all the time.
For this challenge, given a list of strings representing filenames and folders in a directory, do a filesystem sort, explained below:
- Split every string into an array of alternating digits (
0123456789
) and non-digits. If the filename begins with digits, insert an empty string at the beginning of the array. - For each element in the array, if the element is a string, lexicographically sort all the strings by that element in all lowercase or uppercase. If the element is a number, sort by numerical order. If any files are tied, continue to the next element for more specific sorting criteria.
Here is an example, starting with strings that are initially sorted lexicographically:
Abcd.txt
Cat05.jpg
Meme00.jpeg
abc.txt
cat.png
cat02.jpg
cat1.jpeg
meme03-02.jpg
meme03-1.jpeg
meme04.jpg
After step 1, you'll get this:
"Abcd.txt"
"Cat", 5, ".jpg"
"Meme", 0, ".jpeg"
"abc.txt"
"cat.png"
"cat", 2, ".jpg"
"cat", 1, ".jpeg"
"meme", 3, "-", 2, ".jpg"
"meme", 3, "-", 1, ".jpeg"
"meme", 4, ".jpg"
After step 2, you'll get this:
abc.txt
Abcd.txt
cat1.jpeg
cat02.jpg
Cat05.jpg
cat.png
Meme00.jpeg
meme03-1.jpeg
meme03-02.jpg
meme04.jpg
Here are the rules:
- You may not assume the list of input strings is sorted in any order
- You may assume that the input strings only contain printable ASCII characters
- You may assume that when the filenames are converted to all lowercase or all uppercase, there will be no duplicates (i.e., a case-insensitive filesystem)
- Input and output may be specified via any approved default method
- Standard loopholes apply
Here is an example implementation of the sorting algorithm if there is any confusion:
function sort(array) {
function split(file) {
return file.split(/(\D*)(\d*)/);
}
return array.sort((a, b) => {
var c = split(a);
var d = split(b);
for (var i = 0; i < Math.min(c.length, d.length); i++) {
var e = c[i].toLowerCase();
var f = d[i].toLowerCase();
if (e-f) {
return e-f;
}
if (e.localeCompare(f) !== 0) {
return e.localeCompare(f);
}
}
return c.length - d.length;
});
}
This is code-golf, so shortest answer wins!