Wie sortiere ich Zeichenfolgen alphabetisch, während ich den Wert berücksichtige, wenn eine Zeichenfolge numerisch ist?

99

Ich versuche, ein Array von Zahlen zu sortieren, die Zeichenfolgen sind, und ich möchte, dass sie numerisch sortiert werden.

Der Haken ist, dass ich die Zahlen nicht in int konvertieren kann .

Hier ist der Code:

string[] things= new string[] { "105", "101", "102", "103", "90" };

foreach (var thing in things.OrderBy(x => x))
{
    Console.WriteLine(thing);
}

Ausgabe: 101, 102, 103, 105, 90

Ich möchte: 90, 101, 102, 103, 105

EDIT: Die Ausgabe kann nicht 090, 101, 102 sein ...

Das Codebeispiel wurde aktualisiert, um "Dinge" anstelle von "Größen" zu sagen. Das Array kann ungefähr so ​​aussehen:

string[] things= new string[] { "paul", "bob", "lauren", "007", "90" };

Das heißt, es muss alphabetisch und nach Nummern sortiert werden:

007, 90, Bob, Lauren, Paul

sf.
quelle
8
Warum können Sie sie nicht in int konvertieren?
Femaref
1
"Größen" können etwas anderes wie "Name" sein. Das Codebeispiel ist nur vereinfacht.
sf.
2
Wird eine der Zahlen negativ sein? Werden sie alle ganze Zahlen sein? Was ist die Reichweite der ganzen Zahlen?
Eric Lippert
"Dinge" können jede Art von Zeichenfolge sein. Ich möchte, dass die Liste logisch nach einer Person ohne Computerkenntnisse sortiert wird. Negative Zahlen sollten vor dem Postiv stehen. In Bezug auf die Stringlänge werden es nicht mehr als 100 Zeichen sein.
sf.
5
Wie weit willst du gehen? Sollte image10nach kommen image2? Sollte Januaryvorher kommen February?
Svick

Antworten:

103

Übergeben Sie einen benutzerdefinierten Vergleicher an OrderBy. Enumerable.OrderBy können Sie einen beliebigen Vergleicher angeben.

Dies ist eine Möglichkeit, dies zu tun:

void Main()
{
    string[] things = new string[] { "paul", "bob", "lauren", "007", "90", "101"};

    foreach (var thing in things.OrderBy(x => x, new SemiNumericComparer()))
    {    
        Console.WriteLine(thing);
    }
}


public class SemiNumericComparer: IComparer<string>
{
    /// <summary>
    /// Method to determine if a string is a number
    /// </summary>
    /// <param name="value">String to test</param>
    /// <returns>True if numeric</returns>
    public static bool IsNumeric(string value)
    {
        return int.TryParse(value, out _);
    }

    /// <inheritdoc />
    public int Compare(string s1, string s2)
    {
        const int S1GreaterThanS2 = 1;
        const int S2GreaterThanS1 = -1;

        var IsNumeric1 = IsNumeric(s1);
        var IsNumeric2 = IsNumeric(s2);

        if (IsNumeric1 && IsNumeric2)
        {
            var i1 = Convert.ToInt32(s1);
            var i2 = Convert.ToInt32(s2);

            if (i1 > i2)
            {
                return S1GreaterThanS2;
            }

            if (i1 < i2)
            {
                return S2GreaterThanS1;
            }

            return 0;
        }

        if (IsNumeric1)
        {
            return S2GreaterThanS1;
        }

        if (IsNumeric2)
        {
            return S1GreaterThanS2;
        }

        return string.Compare(s1, s2, true, CultureInfo.InvariantCulture);
    }
}
Jeff Paulsen
quelle
1
Für die angegebene Eingabe ergibt sich das gleiche Ergebnis wie für die Antwort von Recursive, an der PadLeft () beteiligt ist. Ich gehe davon aus, dass Ihre Eingabe tatsächlich komplexer ist als in diesem Beispiel gezeigt. In diesem Fall ist ein benutzerdefinierter Vergleicher der richtige Weg.
Jeff Paulsen
Prost. Diese Lösung funktioniert und scheint eine einfach zu lesende und saubere Art der Implementierung zu sein. +1 um mir zu zeigen, dass du IComparer auf OrderBy verwenden kannst :)
sf.
17
Die IsNumericMethode ist schlecht, eine ausnahmegesteuerte Codierung ist immer schlecht. Verwenden Sie int.TryParsestattdessen. Probieren Sie Ihren Code mit einer großen Liste aus und es wird ewig dauern.
Nean Der Thal
Wenn es hilfreich ist, habe ich dieser Version hier eine Erweiterung hinzugefügt , die das Sortieren mit Wörtern unterstützt. Für meine Bedürfnisse war das Aufteilen auf Leerzeichen ausreichend, und ich musste mir kaum Gedanken über Wörter mit gemischter Verwendung machen (z. B. test12 vs test3),
matt.bungard
@NeanDerThal Ich bin mir ziemlich sicher, dass es nur langsam / schlecht ist, viele Ausnahmen in einer Schleife zu behandeln, wenn Sie debuggen oder auf das Exception-Objekt zugreifen.
Kelly Elton
90

Einfach mit Nullen gleicher Länge auffüllen:

int maxlen = sizes.Max(x => x.Length);
var result = sizes.OrderBy(x => x.PadLeft(maxlen, '0'));
rekursiv
quelle
+1 für einfache Lösung, Nitpicking würde (bereits in Bearbeitung gemacht, nett)
Marino Šimić
Gute Idee, aber der nächste Haken ist, dass ich diese Werte dokumentieren muss, damit die "90" eine "90" sein muss, nicht "090"
sf.
6
@sf: Probieren Sie es aus, vielleicht gefällt Ihnen das Ergebnis. Denken Sie daran, dass der Bestellschlüssel nicht bestellt wird. Wenn ich eine Kundenliste nach Nachnamen bestellen möchte, erhalte ich eine Kundenliste, keine Nachnamenliste. Wenn Sie sagen, dass eine Liste von Zeichenfolgen nach einer transformierten Zeichenfolge sortiert werden soll, ist das Ergebnis die geordnete Liste der ursprünglichen Zeichenfolgen, nicht der transformierten Zeichenfolgen.
Eric Lippert
Ich musste "Größen = Größen.OrderBy (...)" hinzufügen, damit dies funktioniert. Ist das normal oder sollte die Antwort bearbeitet werden?
Gorgabal
1
@gorgabal: Im Allgemeinen sizeswürde eine Neuzuweisung zu auch nicht funktionieren, da das Ergebnis ein anderer Typ ist. Die Antwort ist insofern kurz, als die zweite Zeile das Ergebnis als Ausdruck zeigt, aber es liegt am Leser, etwas damit zu tun. Ich habe eine weitere Variablenzuweisung hinzugefügt, um dies klarer zu machen.
rekursiv
74

Und wie wäre es damit ...

string[] sizes = new string[] { "105", "101", "102", "103", "90" };

var size = from x in sizes
           orderby x.Length, x
           select x;

foreach (var p in size)
{
    Console.WriteLine(p);
}
Shenhengbin
quelle
hehe, ich mag dieses wirklich - sehr klug. Entschuldigung, wenn ich nicht den vollständigen Satz der Anfangsdaten angegeben habe
sf.
3
Dies ist genau wie die Pad-Option über nur viel besser IMO.
dudeNumber4
3
var size = size.OrderBy (x => x.Length) .ThenBy (x => x);
Phillip Davis
1
Dies mischt jedoch alphabetische Zeichenfolgen wie folgt : "b", "ab", "101", "103", "bob", "abcd".
Andrew
67

Wert ist eine Zeichenfolge

List = List.OrderBy(c => c.Value.Length).ThenBy(c => c.Value).ToList();

Funktioniert

Echo
quelle
2
Diese Antwort ist mein Favorit.
LacOniC
2
Danke, ich habe gerade festgestellt, dass eine "ThenBy" -Methode beendet wird.
Ganchito55
Dies funktioniert hervorragend für meinen Anwendungsfall, bei dem die Eingabe im Format new erfolgtstring[] { "Object 1", "Object 9", "Object 14" }
am
2
Dies ist die beste Antwort. Es funktioniert und ist gut zu lernen. Vielen Dank !!
Juli
1
Dies mischt jedoch alphabetische Zeichenfolgen wie folgt : "b", "ab", "101", "103", "bob", "abcd".
Andrew
13

In Fenstern gibt es eine native Funktion StrCmpLogicalW, die in Zeichenfolgen Zahlen als Zahlen anstelle von Buchstaben vergleicht. Es ist einfach, einen Vergleicher zu erstellen, der diese Funktion aufruft und für ihre Vergleiche verwendet.

public class StrCmpLogicalComparer : Comparer<string>
{
    [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
    private static extern int StrCmpLogicalW(string x, string y);

    public override int Compare(string x, string y)
    {
        return StrCmpLogicalW(x, y);
    }
}

Es funktioniert sogar mit Zeichenfolgen, die sowohl Text als auch Zahlen enthalten. Hier ist ein Beispielprogramm, das den Unterschied zwischen der Standardsortierung und der StrCmpLogicalWSortierung zeigt

class Program
{
    static void Main()
    {
        List<string> items = new List<string>()
        {
            "Example1.txt", "Example2.txt", "Example3.txt", "Example4.txt", "Example5.txt", "Example6.txt", "Example7.txt", "Example8.txt", "Example9.txt", "Example10.txt",
            "Example11.txt", "Example12.txt", "Example13.txt", "Example14.txt", "Example15.txt", "Example16.txt", "Example17.txt", "Example18.txt", "Example19.txt", "Example20.txt"
        };

        items.Sort();

        foreach (var item in items)
        {
            Console.WriteLine(item);
        }

        Console.WriteLine();

        items.Sort(new StrCmpLogicalComparer());

        foreach (var item in items)
        {
            Console.WriteLine(item);
        }
        Console.ReadLine();
    }
}

welche Ausgänge

Example1.txt
Example10.txt
Example11.txt
Example12.txt
Example13.txt
Example14.txt
Example15.txt
Example16.txt
Example17.txt
Example18.txt
Example19.txt
Example2.txt
Example20.txt
Example3.txt
Example4.txt
Example5.txt
Example6.txt
Example7.txt
Example8.txt
Example9.txt

Example1.txt
Example2.txt
Example3.txt
Example4.txt
Example5.txt
Example6.txt
Example7.txt
Example8.txt
Example9.txt
Example10.txt
Example11.txt
Example12.txt
Example13.txt
Example14.txt
Example15.txt
Example16.txt
Example17.txt
Example18.txt
Example19.txt
Example20.txt
Scott Chamberlain
quelle
Ich wünschte, es wäre einfacher, Systembibliotheken in C # zu verwenden
Kyle Delaney
Das wäre perfekt gewesen, aber es werden leider keine negativen Zahlen verarbeitet. -1 0 10 2ist sortiert als0 -1 2 10
nphx
5

Versuche dies

sizes.OrderBy(x => Convert.ToInt32(x)).ToList<string>();

Hinweis: Dies ist hilfreich, wenn alle Zeichenfolgen in int konvertierbar sind.

Pranay Rana
quelle
1
Dadurch wird der String in einen Int konvertiert.
Femaref
1
"Größen" können auch nicht numerisch sein
sf.
Für "LINQ to SQL" vergessen Sie nicht das ToList()Vorher =>sizes.ToList().OrderBy(x => Convert.ToInt32(x))
A. Morel
5

Ich denke, das ist viel besser, wenn die Zeichenfolge eine Zahl enthält. Hoffe es wird helfen.

PS: Ich bin mir nicht sicher über die Leistung oder komplizierte Zeichenfolgenwerte, aber es hat so gut funktioniert:

lorem ipsum
lorem ipsum 1
lorem ipsum 2
lorem ipsum 3
...
lorem ipsum 20
lorem ipsum 21

public class SemiNumericComparer : IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        int s1r, s2r;
        var s1n = IsNumeric(s1, out s1r);
        var s2n = IsNumeric(s2, out s2r);

        if (s1n && s2n) return s1r - s2r;
        else if (s1n) return -1;
        else if (s2n) return 1;

        var num1 = Regex.Match(s1, @"\d+$");
        var num2 = Regex.Match(s2, @"\d+$");

        var onlyString1 = s1.Remove(num1.Index, num1.Length);
        var onlyString2 = s2.Remove(num2.Index, num2.Length);

        if (onlyString1 == onlyString2)
        {
            if (num1.Success && num2.Success) return Convert.ToInt32(num1.Value) - Convert.ToInt32(num2.Value);
            else if (num1.Success) return 1;
            else if (num2.Success) return -1;
        }

        return string.Compare(s1, s2, true);
    }

    public bool IsNumeric(string value, out int result)
    {
        return int.TryParse(value, out result);
    }
}
Cansın Şenalioğlu
quelle
Genau das, wonach ich gesucht habe. Danke dir!
klugerama
4

Sie sagen, Sie können die Zahlen nicht in int konvertieren, da das Array Elemente enthalten kann, die nicht in int konvertiert werden können, aber es schadet nicht, es zu versuchen:

string[] things = new string[] { "105", "101", "102", "103", "90", "paul", "bob", "lauren", "007", "90" };
Array.Sort(things, CompareThings);

foreach (var thing in things)
    Debug.WriteLine(thing);

Dann vergleiche so:

private static int CompareThings(string x, string y)
{
    int intX, intY;
    if (int.TryParse(x, out intX) && int.TryParse(y, out intY))
        return intX.CompareTo(intY);

    return x.CompareTo(y);
}

Ausgabe: 007, 90, 90, 101, 102, 103, 105, Bob, Lauren, Paul

Ulf Kristiansen
quelle
Übrigens habe ich der Einfachheit halber Array.Sort verwendet, aber Sie könnten dieselbe Logik in einem IComparer verwenden und OrderBy verwenden.
Ulf Kristiansen
Diese Lösung scheint schneller zu sein als IComparer (meiner Meinung nach). 15000 Ergebnis und ich denke, dies ergibt etwa einen zweiten Unterschied.
Jason Foglia
3

Dies scheint eine seltsame Bitte zu sein und verdient eine seltsame Lösung:

string[] sizes = new string[] { "105", "101", "102", "103", "90" };

foreach (var size in sizes.OrderBy(x => {
    double sum = 0;
    int position = 0;
    foreach (char c in x.ToCharArray().Reverse()) {
        sum += (c - 48) * (int)(Math.Pow(10,position));
        position++;
    }
    return sum;
}))

{
    Console.WriteLine(size);
}
Marino Šimić
quelle
Ich meinte natürlich 0x30. Das Array kann auch noch eine nicht numerische Zeichenfolge enthalten, für die die Lösung interessante Ergebnisse liefert.
Femaref
Und beachten Sie, dass die -48 oder nicht absolut nichts ändert, wir könnten direkt den ganzzahligen Wert des Zeichens verwenden, also entfernen Sie diese -48, wenn es Sie stört ...
Marino Šimić
Der char-Wert ist 0x30, wenn Sie das in int konvertieren, wird es immer noch 0x30 sein, was nicht die Zahl 0 ist.
Femaref
Das einzige, was in eine Ganzzahl umgewandelt wird, ist das Double, das von Math.Pow
Marino Šimić am
Wenn es egal ist, ob es Null ist oder nicht, das dekadische System kümmert sich darum, es könnte ein Đ sein, wenn Sie wollen, das einzige, was zählt, dass die Zahlen im Zeichensatz in aufsteigender Reihenfolge sind und weniger als 10
Marino Šimić
3

Diese Site behandelt die alphanumerische Sortierung und sortiert die Zahlen in einem logischen Sinn anstelle eines ASCII-Sinns. Es berücksichtigt auch die Alphas um ihn herum:

http://www.dotnetperls.com/alphanumeric-sorting

BEISPIEL:

  • C: /TestB/333.jpg
  • 11
  • C: /TestB/33.jpg
  • 1
  • C: /TestA/111.jpg
  • 111F
  • C: /TestA/11.jpg
  • 2
  • C: /TestA/1.jpg
  • 111D
  • 22
  • 111Z
  • C: /TestB/03.jpg

  • 1
  • 2
  • 11
  • 22
  • 111D
  • 111F
  • 111Z
  • C: /TestA/1.jpg
  • C: /TestA/11.jpg
  • C: /TestA/111.jpg
  • C: /TestB/03.jpg
  • C: /TestB/33.jpg
  • C: /TestB/333.jpg

Der Code lautet wie folgt:

class Program
{
    static void Main(string[] args)
    {
        var arr = new string[]
        {
           "C:/TestB/333.jpg",
           "11",
           "C:/TestB/33.jpg",
           "1",
           "C:/TestA/111.jpg",
           "111F",
           "C:/TestA/11.jpg",
           "2",
           "C:/TestA/1.jpg",
           "111D",
           "22",
           "111Z",
           "C:/TestB/03.jpg"
        };
        Array.Sort(arr, new AlphaNumericComparer());
        foreach(var e in arr) {
            Console.WriteLine(e);
        }
    }
}

public class AlphaNumericComparer : IComparer
{
    public int Compare(object x, object y)
    {
        string s1 = x as string;
        if (s1 == null)
        {
            return 0;
        }
        string s2 = y as string;
        if (s2 == null)
        {
            return 0;
        }

        int len1 = s1.Length;
        int len2 = s2.Length;
        int marker1 = 0;
        int marker2 = 0;

        // Walk through two the strings with two markers.
        while (marker1 < len1 && marker2 < len2)
        {
            char ch1 = s1[marker1];
            char ch2 = s2[marker2];

            // Some buffers we can build up characters in for each chunk.
            char[] space1 = new char[len1];
            int loc1 = 0;
            char[] space2 = new char[len2];
            int loc2 = 0;

            // Walk through all following characters that are digits or
            // characters in BOTH strings starting at the appropriate marker.
            // Collect char arrays.
            do
            {
                space1[loc1++] = ch1;
                marker1++;

                if (marker1 < len1)
                {
                    ch1 = s1[marker1];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

            do
            {
                space2[loc2++] = ch2;
                marker2++;

                if (marker2 < len2)
                {
                    ch2 = s2[marker2];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch2) == char.IsDigit(space2[0]));

            // If we have collected numbers, compare them numerically.
            // Otherwise, if we have strings, compare them alphabetically.
            string str1 = new string(space1);
            string str2 = new string(space2);

            int result;

            if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
            {
                int thisNumericChunk = int.Parse(str1);
                int thatNumericChunk = int.Parse(str2);
                result = thisNumericChunk.CompareTo(thatNumericChunk);
            }
            else
            {
                result = str1.CompareTo(str2);
            }

            if (result != 0)
            {
                return result;
            }
        }
        return len1 - len2;
    }
}
Chad Kuehn
quelle
2

Die Antwort von Jeff Paulsen ist richtig, aber das Comprarerkann sehr vereinfacht werden:

public class SemiNumericComparer: IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (IsNumeric(s1) && IsNumeric(s2))
          return Convert.ToInt32(s1) - Convert.ToInt32(s2)

        if (IsNumeric(s1) && !IsNumeric(s2))
            return -1;

        if (!IsNumeric(s1) && IsNumeric(s2))
            return 1;

        return string.Compare(s1, s2, true);
    }

    public static bool IsNumeric(object value)
    {
        int result;
        return Int32.TryParse(value, out result);
    }
}

Dies funktioniert, weil das einzige, was auf das Ergebnis der überprüft wird Comparer wird, wenn das Ergebnis größer, kleiner oder gleich Null ist. Man kann einfach die Werte von einem anderen subtrahieren und muss die Rückgabewerte nicht verarbeiten.

Auch sollte die IsNumericMethode keinen try-block verwenden müssen und kann davon profitieren TryParse.

Und für diejenigen, die sich nicht sicher sind: Dieser Vergleicher sortiert die Werte so, dass nicht numerische Werte immer an das Ende der Liste angehängt werden. Wenn man sie am Anfang ifhaben will, müssen der zweite und dritte Block getauscht werden.

k-Mutter
quelle
Da das Aufrufen der TryParse-Methode wahrscheinlich einen gewissen Overhead hat, würde ich die isNumeric-Werte für s1 und s2 zuerst in booleschen Werten speichern und stattdessen den Vergleich für diese durchführen. Auf diese Weise werden sie nicht mehrfach ausgewertet.
Optavius
1

Versuche dies :

string[] things= new string[] { "105", "101", "102", "103", "90" };

int tmpNumber;

foreach (var thing in (things.Where(xx => int.TryParse(xx, out tmpNumber)).OrderBy(xx =>     int.Parse(xx))).Concat(things.Where(xx => !int.TryParse(xx, out tmpNumber)).OrderBy(xx => xx)))
{
    Console.WriteLine(thing);
}
TMAmine
quelle
1
public class NaturalSort: IComparer<string>
{
          [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
          public static extern int StrCmpLogicalW(string x, string y);

          public int Compare(string x, string y)
          {
                 return StrCmpLogicalW(x, y);
          }
}

arr = arr.OrderBy (x => x, neues NaturalSort ()). ToArray ();

Der Grund, warum ich es brauchte, war, in einem Verzeichnis abgelegt zu werden, dessen Dateinamen mit einer Nummer begannen:

public static FileInfo[] GetFiles(string path)
{
  return new DirectoryInfo(path).GetFiles()
                                .OrderBy(x => x.Name, new NaturalSort())
                                .ToArray();
}
Neil M.
quelle
0
Try this out..  



  string[] things = new string[] { "paul", "bob", "lauren", "007", "90", "-10" };

        List<int> num = new List<int>();
        List<string> str = new List<string>();
        for (int i = 0; i < things.Count(); i++)
        {

            int result;
            if (int.TryParse(things[i], out result))
            {
                num.Add(result);
            }
            else
            {
                str.Add(things[i]);
            }


        }

Sortieren Sie nun die Listen und führen Sie sie wieder zusammen ...

        var strsort = from s in str
                      orderby s.Length
                      select s;

        var numsort = from n in num
                     orderby n
                     select n;

        for (int i = 0; i < things.Count(); i++)
        {

         if(i < numsort.Count())
             things[i] = numsort.ElementAt(i).ToString();
             else
             things[i] = strsort.ElementAt(i - numsort.Count());               
               }

Ich habe nur versucht, einen Beitrag zu dieser interessanten Frage zu leisten ...

Syeda
quelle
0

Meine bevorzugte Lösung (wenn alle Zeichenfolgen nur numerisch sind):

// Order by numerical order: (Assertion: all things are numeric strings only) 
foreach (var thing in things.OrderBy(int.Parse))
{
    Console.Writeline(thing);
}
Bug Raptor
quelle
0
public class Test
{
    public void TestMethod()
    {
        List<string> buyersList = new List<string>() { "5", "10", "1", "str", "3", "string" };
        List<string> soretedBuyersList = null;

        soretedBuyersList = new List<string>(SortedList(buyersList));
    }

    public List<string> SortedList(List<string> unsoredList)
    {
        return unsoredList.OrderBy(o => o, new SortNumericComparer()).ToList();
    }
}

   public class SortNumericComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        int xInt = 0;
        int yInt = 0;
        int result = -1;

        if (!int.TryParse(x, out xInt))
        {
            result = 1;
        }

        if(int.TryParse(y, out yInt))
        {
            if(result == -1)
            {
                result = xInt - yInt;
            }
        }
        else if(result == 1)
        {
             result = string.Compare(x, y, true);
        }

        return result;
    }
}
Kumar
quelle
Können Sie Ihren Code erklären ? Nur-Code-Antworten können gelöscht werden.
Wai Ha Lee
Der Beitrag von Jeff Paulsen hat mir geholfen, IComparer <string> zu implementieren, um mein schmerzendes Problem zu beheben. .
Kumar
0

Jeff Paulsen Antwort erweitern. Ich wollte sicherstellen, dass es keine Rolle spielt, wie viele Zahlen- oder Zeichengruppen in den Zeichenfolgen enthalten sind:

public class SemiNumericComparer : IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (int.TryParse(s1, out var i1) && int.TryParse(s2, out var i2))
        {
            if (i1 > i2)
            {
                return 1;
            }

            if (i1 < i2)
            {
                return -1;
            }

            if (i1 == i2)
            {
                return 0;
            }
        }

        var text1 = SplitCharsAndNums(s1);
        var text2 = SplitCharsAndNums(s2);

        if (text1.Length > 1 && text2.Length > 1)
        {

            for (var i = 0; i < Math.Max(text1.Length, text2.Length); i++)
            {

                if (text1[i] != null && text2[i] != null)
                {
                    var pos = Compare(text1[i], text2[i]);
                    if (pos != 0)
                    {
                        return pos;
                    }
                }
                else
                {
                    //text1[i] is null there for the string is shorter and comes before a longer string.
                    if (text1[i] == null)
                    {
                        return -1;
                    }
                    if (text2[i] == null)
                    {
                        return 1;
                    }
                }
            }
        }

        return string.Compare(s1, s2, true);
    }

    private string[] SplitCharsAndNums(string text)
    {
        var sb = new StringBuilder();
        for (var i = 0; i < text.Length - 1; i++)
        {
            if ((!char.IsDigit(text[i]) && char.IsDigit(text[i + 1])) ||
                (char.IsDigit(text[i]) && !char.IsDigit(text[i + 1])))
            {
                sb.Append(text[i]);
                sb.Append(" ");
            }
            else
            {
                sb.Append(text[i]);
            }
        }

        sb.Append(text[text.Length - 1]);

        return sb.ToString().Split(' ');
    }
}

Ich habe auch SplitCharsAndNums von einer SO-Seite genommen, nachdem ich sie geändert hatte, um sie mit Dateinamen zu behandeln.

Tod
quelle
-1

Obwohl dies eine alte Frage ist, möchte ich eine Lösung geben:

string[] things= new string[] { "105", "101", "102", "103", "90" };

foreach (var thing in things.OrderBy(x => Int32.Parse(x) )
{
    Console.WriteLine(thing);
}

Woha ganz einfach, oder? : D.

Oscar Ortiz
quelle
-1
namespace X
{
    public class Utils
    {
        public class StrCmpLogicalComparer : IComparer<Projects.Sample>
        {
            [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
            private static extern int StrCmpLogicalW(string x, string y);


            public int Compare(Projects.Sample x, Projects.Sample y)
            {
                string[] ls1 = x.sample_name.Split("_");
                string[] ls2 = y.sample_name.Split("_");
                string s1 = ls1[0];
                string s2 = ls2[0];
                return StrCmpLogicalW(s1, s2);
            }
        }

    }
}
hamid ramezanali
quelle