I need to sort file names as follows: 1.log, 2.log, 10.log
But when I use OrderBy(fn => fn) it will sort them as: 1.log, 10.log, 2.log
I obviously know that this could be done by writing another comparer, but is there a simpler way to change from lexicographical order to natural sort order?
Edit: the objective is to obtain the same ordering as when selecting "order by name" in Windows Explorer.
You can do something like this when you can assure the format of your names are NUMBER.VALUE:
It would be easier if it would be a lexicographical order,.
String comparison is always letter by letter.
How you want to deal with that without looking at the whole number?
No, a separate comparer is the only solution.
You can use the Win32
CompareStringEx
function. On Windows 7 it supports the sorting you need. You will have use P/Invoke:You can then create an
IComparer
that uses theSORT_DIGITSASNUMBERS
flag:You can then use the
IComparer
in various sorting API's:You can also use StrCmpLogicalW which is the function used by Windows Explorer. It has been available since Windows XP:
Simpler, but you have less control over the comparison.
no I don't think so - I guess you have to write it yourself as long as your data is just a string. If you make your data into something like
you can sort by using the LogBase-Field
You could just remove all the non digit characters, parse to int and then sort:
If your file names always only consist in digits, you can use Path.GetFileNameWithoutExtension() to discard the file extension and Convert.ToInt32() (or similar) to convert your file names to integers for comparison purposes:
In the general case, or if you're looking for a more "standard" way to do this, you can p/invoke StrCmpLogicalW(), which Explorer uses to sort file names in its views. However, doing that will force you to implement an
IComparer<string>
if you want to useOrderBy()
.