È possibile utilizzare la funzione Win32 CompareStringEx
. Su Windows 7 supporta l'ordinamento di cui hai bisogno. Avrete uso P/Invoke:
static readonly Int32 NORM_IGNORECASE = 0x00000001;
static readonly Int32 NORM_IGNORENONSPACE = 0x00000002;
static readonly Int32 NORM_IGNORESYMBOLS = 0x00000004;
static readonly Int32 LINGUISTIC_IGNORECASE = 0x00000010;
static readonly Int32 LINGUISTIC_IGNOREDIACRITIC = 0x00000020;
static readonly Int32 NORM_IGNOREKANATYPE = 0x00010000;
static readonly Int32 NORM_IGNOREWIDTH = 0x00020000;
static readonly Int32 NORM_LINGUISTIC_CASING = 0x08000000;
static readonly Int32 SORT_STRINGSORT = 0x00001000;
static readonly Int32 SORT_DIGITSASNUMBERS = 0x00000008;
static readonly String LOCALE_NAME_USER_DEFAULT = null;
static readonly String LOCALE_NAME_INVARIANT = String.Empty;
static readonly String LOCALE_NAME_SYSTEM_DEFAULT = "!sys-default-locale";
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern Int32 CompareStringEx(
String localeName,
Int32 flags,
String str1,
Int32 count1,
String str2,
Int32 count2,
IntPtr versionInformation,
IntPtr reserved,
Int32 param
);
È possibile quindi creare un IComparer
che utilizza il flag SORT_DIGITSASNUMBERS
:
class LexicographicalComparer : IComparer<String> {
readonly String locale;
public LexicographicalComparer() : this(CultureInfo.CurrentCulture) { }
public LexicographicalComparer(CultureInfo cultureInfo) {
if (cultureInfo.IsNeutralCulture)
this.locale = LOCALE_NAME_INVARIANT;
else
this.locale = cultureInfo.Name;
}
public Int32 Compare(String x, String y) {
// CompareStringEx return 1, 2, or 3. Subtract 2 to get the return value.
return CompareStringEx(
this.locale,
SORT_DIGITSASNUMBERS, // Add other flags if required.
x,
x.Length,
y,
y.Length,
IntPtr.Zero,
IntPtr.Zero,
0) - 2;
}
}
è quindi possibile utilizzare il IComparer
in vari ordinamento API:
var names = new [] { "2.log", "10.log", "1.log" };
var sortedNames = names.OrderBy(s => s, new LexicographicalComparer());
È inoltre possibile utilizzare StrCmpLogicalW, che è la funzione utilizzata da Esplora risorse. È disponibile da Windows XP:
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
static extern Int32 StrCmpLogical(String x, String y);
class LexicographicalComparer : IComparer<String> {
public Int32 Compare(String x, String y) {
return StrCmpLogical(x, y);
}
}
Più semplice, ma si ha meno controllo sul confronto.
Probabilmente non molto veloce, ma la soluzione più succinta che non richiede la modifica dei nomi dei file in altre cose. –
Questo è debole. Mette 1.10 dopo il 10.1 –
@Chris ordina 100000 elementi in 0,2 secondi. Spero che non abbia comunque tanti file di log –