Laden...

Compare strings special order [natural sorting]

Erstellt von rollerfreak2 vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.546 Views
rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 13 Jahren
Compare strings special order [natural sorting]

Hallo zusammen,

eine kleine Frage bezüglich string compare. Ein normaler string compare "sortiert" folgende 3 strings "item_2", "item_1", "item_11".

Das Ergebnis lautet wenig überaschend: "item_1", "item_11", "item_2".
Ich möchte aber folgendes "item_1", "item_2", "item_11". Dabei soll es aber auch egal sein, was hinter der Zahl steht. Daher "item_1z" kommt vor "item_11".

Gibt es da irgendeine Compare logik die das schon beherscht, oder muss ich selber via Regex anfangen was zu implementieren.

Mein Plan wäre foldender:

  1. Mit regex aus beiden string's den kompletten Anfangsteil + Digit's extrahieren.
  2. Ist einer von beiden matches negativ, den normalen string compare anwerfen.
  3. Sind beide matches positiv, dann wird zu erst geprüft ob die beiden "anfangs" string gleich sind, wenn nicht wieder den normalen string compare anwerfen
  4. Bin ich bis hier her gekommen einfach die beiden Zahlen miteinander vergleichen, sind diese zufällig gleich, dann einfach den normalen string compare anwerfen

Hat jemand einen besseren Vorschlag?

Again what learned...

D
67 Beiträge seit 2006
vor 13 Jahren

Moin,

ich wüsste grad keinen feritgen Comparer, der sowas schon kann. (Lasse mich aber auch gerne belehren.

Wie liegen dir die Strings vor? Als List oder Array oder... ?
Trifft auf jeden String das Must item_x (x ist eine Zahl) zu?

Willst du nur nach der Zahl sortieren oder spielt der String, der vor der Zahl steht, auch eine Rolle?

Grüße
DavidG

„Ich erfand den Begriff «objekt-orientiert», und ich kann sagen, dass ich dabei nicht C++ im Sinn hatte.“ Alan Kay

rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 13 Jahren

Die strings liegen als string's vor, daher ein Comparer Implementieren und dort dann das CompareTo implementieren.

Fertige Sortierungen:

"affe_1", "egon_2"

"af2fe_1", "af2fe_2", "af2fe_11"

"af1fe_2", "af2fe_1", "af2fe_11"

....

Willst du nur nach der Zahl sortieren oder spielt der String, der vor der Zahl steht, auch eine Rolle?

Siehe Muster oben.

Trifft auf jeden String das Must item_x (x ist eine Zahl) zu?

Nein, ich würde es mal so matchen: "^[A-Za-z0-9_]*(\d)+"

Wie liegen dir die Strings vor? Als List oder Array oder... ?

Also generische list, aber was hat das mit der Frage zu tun?


list.Sort(new MyComparer());

Again what learned...

D
67 Beiträge seit 2006
vor 13 Jahren

Wie wäre es, wenn du dir eine Klasse für die einzelne Items baust. In der Klasse hast du ein Feld für den Zahlenwert und ein Feld für den String Wert. Desweiteren implementiert die Klasse das Interface IComparable<T>. Du musst die Methode CompareTo(Item item) ausimplementieren. Dort überprüfen, ob der die Stringwerte gleich sind. Ist dies der Fall, die Zahlenwerte miteinander verlgeichen.

Anschließend kannst du über List.Sort() die Liste sortieren lassen.

z.b.

    
public class Item : IComparable<Item>
    {
        private int _digit;

        private string _str;

        public int Digit
        {
            get { return _digit; }
            set { _digit = value; }
        }

        public string Str
        {
            get { return _str; }
            set { _str = value; }
        }

        public int CompareTo(Item other)
        {
            if(_str.CompareTo(other.Str)== 0)
            {
                return _digit.CompareTo(other.Digit);
            }

            return _str.CompareTo(other.Str);
        }
    }

„Ich erfand den Begriff «objekt-orientiert», und ich kann sagen, dass ich dabei nicht C++ im Sinn hatte.“ Alan Kay

rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 13 Jahren

In der Klasse hast du ein Feld für den Zahlenwert und ein Feld für den String Wert.

Wie gesagt der Wert liegt als STRING vor, deine Lösung funzt also so nicht. Ich müsste erst die digits nach einem speziellen pattern extrahieren, wie ich oben aufgezeigt habe. Das ist ja eigentlich die Problem Stellung, deine aufgezeigte Lösung setzt die eigentliche Lösung ja schon voraus.

Die beiden Links von Th69 sehen sehr vielversprechend aus. Die schau ich mir mal an. Danke

Again what learned...

I
279 Beiträge seit 2008
vor 13 Jahren

Versuchs mal mit "natural sorting"

D
67 Beiträge seit 2006
vor 13 Jahren

Naja, mir war nicht genau so klar, wo dein Problem liegt und nachdem du schon ein Regex-Pattern gepostet hattest, dachte ich, dass du diese Problem schon gelöst hättest.

Du kannst ja den String-Wert in einen Int Wert casten.

Für Reguläre-Ausdrücke gibt es ein klasse Tool (Regex-Lab) von herbivore mit dem man Patterns erstellen / testen kann: Regex-Lab

Das Pattern, mit dem du zum einen den String-Wert (z.B. Affe) und anschließend den numerischen Wert (1) bekommst, lautet: (\w+)_(\d+)

Bei "affe_1" bekommst du somit für den ersten Wert affe und für den zweiten wert die 1.

Ein Regex-Tutorial gibt es hier: Regex Tutorial

So könntest du auch Match-Ergebnisse zu greifen:


Regex myRegex = new Regex("(\\w+)_(\\d+)");
Match myMatch = myRegex.Match(content);

while (myMatch.Success)
{
     string stringValue = myMatch.Groups[1].Value;
     int digitValue =  int.Parse( myMatch.Groups[2].Value)

     myMatch = myMatch.NextMatch();
}

Und so hättest du die einzelnen Werte

„Ich erfand den Begriff «objekt-orientiert», und ich kann sagen, dass ich dabei nicht C++ im Sinn hatte.“ Alan Kay

D
67 Beiträge seit 2006
vor 13 Jahren

Oder wenn du ausschließen kannst, dass nach dem _ was anderes als zahlen kommst, könntest du den string auch mit string.Split("_") teilen

„Ich erfand den Begriff «objekt-orientiert», und ich kann sagen, dass ich dabei nicht C++ im Sinn hatte.“ Alan Kay

rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 13 Jahren

Für Reguläre-Ausdrücke gibt es ein klasse Tool (Regex-Lab) von herbivore mit dem man Patterns erstellen / testen kann: Regex-Lab

Das weis ich schon danach habe ich ja gar nicht gefragt.

Ein Regex-Tutorial gibt es hier: Regex Tutorial

Ich weis mit Regex um zu gehen, es ging nur darum nicht etwas zu implementieren was es bereits gibt. Und dazu hat Th69 die passende Antwort gehabt.

Again what learned...

D
67 Beiträge seit 2006
vor 13 Jahren

wohl ein missverständnis

„Ich erfand den Begriff «objekt-orientiert», und ich kann sagen, dass ich dabei nicht C++ im Sinn hatte.“ Alan Kay

49.485 Beiträge seit 2005
vor 13 Jahren
rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 13 Jahren

Hallo herbivore,

danke noch mal für den Link. Der 2te Link von Th69 sah auch viel verprechend aus und funktioniert soweit ohne Fehler. Er ist auch sehr schnell, ob nun aber die Implementierung deines Links oder des externen schneller ist, habe ich noch nicht ausprobiert.

Again what learned...

D
67 Beiträge seit 2006
vor 13 Jahren

natural sorting klingt echt interessant und jetzt habe ich auch gecheckt, was du wolltest.

„Ich erfand den Begriff «objekt-orientiert», und ich kann sagen, dass ich dabei nicht C++ im Sinn hatte.“ Alan Kay