2009-10-21 10 views
8

Für natürliche Sortierung in meiner Anwendung ich P/Invoke derzeit eine Funktion namens StrCmpLogicalW in shlwapi.dll. Ich habe darüber nachgedacht, meine Anwendung unter Mono laufen zu lassen, aber natürlich kann ich dieses P/Invoke-Zeug nicht haben (so weit ich weiß).C#: Implementierung von oder Alternative zu StrCmpLogicalW in shlwapi.dll

Ist es möglich, die Implementierung dieser Methode irgendwo zu sehen, oder gibt es ein gutes, sauberes und effizientes C# -Snippet, das dasselbe tut?

Mein Code sieht derzeit wie folgt aus:

[SuppressUnmanagedCodeSecurity] 
internal static class SafeNativeMethods 
{ 
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] 
    public static extern int StrCmpLogicalW(string psz1, string psz2); 
} 

public class NaturalStringComparer : IComparer<string> 
{ 
    private readonly int modifier = 1; 

    public NaturalStringComparer() : this(false) {} 
    public NaturalStringComparer(bool descending) 
    { 
     if (descending) modifier = -1; 
    } 

    public int Compare(string a, string b) 
    { 
     return SafeNativeMethods.StrCmpLogicalW(a ?? "", b ?? "") * modifier; 
    } 
} 

Also, was ich suche eine Alternative zu der obigen Klasse ist, die keine externe Funktion nicht verwendet.

+0

Ich fand gerade diese [Blog-Post auf natürliche Sortierung] (http://www.interact-sw.co.uk/iangblog/2007/ 12/13/natürliche Sortierung) in C#. Ist das von Nutzen? Als Antwort auf Ihren Kommentar - ich habe es nicht sehr detailliert analysiert, es sah einfach vielversprechend aus. Es muss andere C# Implementierungen der natürlichen Sortierung da draußen geben, vielleicht müssen Sie nur einen finden und es profilieren? – ChrisF

+0

Gerade fertig gelesen es tatsächlich: P Es schien zu tun, was ich denke, dass es sollte, aber es scheint auch ziemlich ineffizient ... Ich weiß es nicht wirklich ... hehe. – Svish

Antwort

10

I natürliche String-Vergleich in C# nur implementiert, vielleicht jemand könnte es nützlich finden:

public class NaturalComparer : IComparer<string> 
{ 
    public int Compare(string x, string y) 
    { 
     if (x == null && y == null) return 0; 
     if (x == null) return -1; 
     if (y == null) return 1; 

     int lx = x.Length, ly = y.Length; 

     for (int mx = 0, my = 0; mx < lx && my < ly; mx++, my++) 
     { 
     if (char.IsDigit(x[mx]) && char.IsDigit(y[my])) 
     { 
      long vx = 0, vy = 0; 

      for (; mx < lx && char.IsDigit(x[mx]); mx++) 
       vx = vx * 10 + x[mx] - '0'; 

      for (; my < ly && char.IsDigit(y[my]); my++) 
       vy = vy * 10 + y[my] - '0'; 

      if (vx != vy) 
       return vx > vy ? 1 : -1; 
     } 

     if (mx < lx && my < ly && x[mx] != y[my]) 
      return x[mx] > y[my] ? 1 : -1; 
     } 

     return lx - ly; 
    } 
} 
+0

ist nicht vollständig, wenn Sie ex1, ex-3, ex2 haben, dann wird die ex-3 zuletzt. Die pinvoke windows Funktion natürlicher Sortieralgorithmus macht es Explorer ähnlich. –

0

I regulären Ausdruck Sonderzeichen zu entfernen. dann Casting nach int. dann habe ich ganze Zahlen verglichen.

Eingang:

 
List input = new List{ "6.04","6.01","6.03","6#04" };
Erwartete Ausgabe:

 
6.01 
6.03 
6.04 
6#04 
 

var output = input.OrderBy(s => s, new NaturalStringComparer()); 
      foreach (var sort in output) 
      { 
       Console.WriteLine(sort); 
      } 


public struct NaturalStringComparer : IComparer 
    { 
     public int Compare(string x, string y) 
     { 
      if (x == null && y == null) return 0; 
      if (x == null) return -1; 
      if (y == null) return 1; 

      int lx = x.Length, ly = y.Length; 

      int a = int.Parse(System.Text.RegularExpressions.Regex.Replace(x, @"\D+", "")); 
      int b = int.Parse(System.Text.RegularExpressions.Regex.Replace(y, @"\D+", "")); 

      return a.CompareTo(b); 
     } 
    } 
+0

Bitte kommentieren. wenn Sie leistungsbezogene Probleme finden. mache ich irgendwas falsches string int. –