C ++ - String wie ein Mensch sortieren?

8

Ich möchte alphanumerische Zeichenfolgen so sortieren, wie ein Mensch sie sortieren würde. Das heißt, "A2" kommt vor "A10" und "a" kommt sicherlich vor "Z"! Gibt es einen Weg, ohne einen Mini-Parser zu schreiben? Idealerweise würde "A1B1" auch vor "A1B10" stehen. Ich sehe die Frage "Natürlich (menschlich alphanumerisch) sortieren" Microsoft SQL 2005 " mit einer möglichen Antwort, aber es verwendet verschiedene Bibliotheksfunktionen, wie auch " Sortierfolgen für Menschen mit IComparer ".

Unten ist ein Testfall, der momentan fehlschlägt:

%Vor%     
Walter Nissen 23.05.2017, 11:53
quelle

4 Antworten

5

Gibt es eine Möglichkeit, ohne einen Mini-Parser zu schreiben?

Lassen Sie jemand anderes das tun?

Ich verwende diese Implementierung: Ссылка , ich habe sie so modifiziert, dass sie auch wchar_t unterstützt.

>     
peterchen 06.05.2010, 20:19
quelle
2

Es hängt wirklich davon ab, was Sie mit "Parser" meinen. Wenn Sie vermeiden möchten, einen Parser zu schreiben, würde ich denken, dass Sie Bibliotheksfunktionen in Anspruch nehmen sollten.

  • Behandle die Zeichenfolge als eine Folge von Teilfolgen, die einheitlich alphabetisch, numerisch oder "anders" sind.
  • Erhalten Sie die nächste alphanumerische Sequenz für jeden String mit isalnum und Backtrack-checking für + oder - , wenn es sich um eine Zahl handelt. Verwenden Sie strtold in-place, um das Ende einer numerischen Untersequenz zu finden.
  • Wenn eins numerisch und eins alphabetisch ist, steht die Zeichenfolge mit der numerischen Untersequenz an erster Stelle.
  • Wenn eine Zeichenfolge keine Zeichen mehr enthält, kommt sie zuerst.
  • Verwenden Sie strcoll , um alphabetische Untersequenzen innerhalb des aktuellen Gebietsschemas zu vergleichen.
  • Verwenden Sie strtold , um numerische Untersequenzen im aktuellen Gebietsschema zu vergleichen.
  • Wiederholen Sie den Vorgang, bis Sie mit einer oder beiden Zeichenfolgen fertig sind.
  • Bricht Beziehungen mit strcmp .
  • ab

Dieser Algorithmus hat eine Schwäche beim Vergleich numerischer Zeichenfolgen, die die Genauigkeit von long double überschreiten.

    
Potatoswatter 06.05.2010 20:30
quelle
0

Gibt es eine Möglichkeit, dies zu tun, ohne einen Mini-Parser zu schreiben? Ich würde denken, die Antwort ist nein. Aber einen Parser zu schreiben ist nicht so schwierig. Ich musste dies vor einiger Zeit tun, um die Bestandszahlen unserer Firma zu sortieren. Im Grunde scannen Sie einfach die Nummer und verwandeln Sie sie in ein Array. Überprüfen Sie den "Typ" jedes Charakters: Alpha, Zahl, vielleicht haben Sie andere, mit denen Sie sich beschäftigen müssen. So wie ich Bindestriche behandeln musste, weil wir A-B-C vor AB-A sortieren wollten. Dann fangen Sie an, Charaktere abzuziehen. Solange sie den gleichen Typ wie das erste Zeichen haben, gehen sie in den gleichen Eimer. Sobald sich der Typ ändert, fängst du an, sie in einen anderen Eimer zu legen. Dann benötigen Sie auch eine Vergleichsfunktion, die Bucket für Bucket vergleicht. Wenn beide Buckets Alpha sind, machen Sie nur einen normalen Alpha-Vergleich. Wenn beide Ziffern sind, wandeln Sie beide in Integer um und machen Sie einen Integer-Vergleich, oder puffern Sie den kürzeren auf die Länge des längeren oder etwas Äquivalentes. Wenn sie unterschiedliche Typen sind, benötigen Sie eine Regel für den Vergleich, wie kommt A-A vor oder nach A-1?

Es ist keine triviale Aufgabe und Sie müssen Regeln für all die seltsamen Fälle aufstellen, die auftreten können, aber ich würde denken, dass Sie es in ein paar Stunden Arbeit zusammenbringen könnten.

    
Jay 06.05.2010 19:51
quelle
0

Ohne Parsing gibt es keine Möglichkeit, geschriebene Zahlen (hohe Werte zuerst mit führenden Nullen) und normale Zeichen als Teil derselben Zeichenfolge zu vergleichen.

Das Parsen muss jedoch nicht sehr komplex sein. Eine einfache Hash-Tabelle, die sich mit Groß- und Kleinschreibung und Sonderzeichen auseinandersetzt ('A' = 'a' = 1, 'B' = 'b' = '2, ... oder' A '= 1,' a ') = 2, 'B' = 3, ..., '-' = 0 (strip)), ordnen Sie die Zeichenkette einem Array der Hashwerte zu und schneiden Sie dann die Anzahl der Fälle ab (wenn eine Zahl gefunden wurde und das letzte Zeichen a war) Nummer, multipliziere die letzte Zahl mit zehn und füge den aktuellen Wert hinzu.)

Von dort sortiere wie normal.

    
pdehaan 06.05.2010 20:15
quelle

Tags und Links