Strings die Zahlen enthalten sinnvoll sortieren (A2 < A10

  • Themenstarter Themenstarter Guest
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
G

Guest

Gast
Hi Leute,

hat zufällig schonmal jemand einen vernünftigen StringComparator geschrieben, der auch Zahlen in Strings erkennt und sinnvoll sortieren kann? Ich hab jetzt das Problem dass das compareTo von String das meint: A1 < A10 < A2 < A3. Weil die 10 nicht zusammenhängend ausgewertet wird.

Oder hat jemand einen Ansatz mit dem ich schnell an mein Ziel komme? Eine statische Lösung (einfach "A" abschneiden) wird nicht funktionieren, da auch vollkommen andere Strings vorkommen könnten.

Danke schonmal im Voraus! 🙂

Gruß Nova
 
Ich kenne nur wenige "alltägliche" Probleme, bei denen Regular Expressions eine passende Lösung darstellen, aber DAS wäre eine: Damit kann man relativ leicht Zahlen in Strings finden, die man dann einfach rausparsen kann.
 
Hm, das wäre dann aber ein ziemlich komplexer Regular Expression, weil ja nicht nur die Zahlen rausgeparsed und vergleichen, sondern auch die restlichen Strings zwischen den Zahlen berücksichtigt werden müssen. Und mit Regular Expressions kenne ich mich nicht wirklich gut aus... :-(
 
Ich auch nicht. Wieder dieser alte Spruch: "Wenn du ein Problem hast, und jemand sagt, du solltest es mit RegularExpressions lösen, hast du auf einmal ZWEI Probleme" :wink: Aber in diesem Fall ist die Regular Expression selbst garnicht so kompliziert: "\\d+". Etwas fummeliger ist, die ganzen matches durchzugehen, und im richtigen Moment richtig zu returnen. Was bei einem Vergleich zweier Strings wie
abc012def
abc12def
rauskommen soll (beide male steht "eigentlich" nur 12 da...) mal ganz außen vor gelassen.

Hab da mal was gebastelt - ist aber nicht so ausführlich getestet und nur ziemlich schnell hingeschrieben - das könnte man vmlt. schöner, einfacher, eleganter, was-weiß-ich-wie machen, aber vielleicht hilft's zumindest als ansatz...
Code:
import java.util.regex.*;
import java.util.*;
import java.io.*;

class NumberStringComparator implements Comparator<String>
{
    public static void main(String args[])
    {
        NumberStringComparator n = new NumberStringComparator();

        System.out.println(n.compare("abc","abc")==0);
        System.out.println(n.compare("abc12","abc")>0);
        System.out.println(n.compare("abc12","abc12")==0);
        System.out.println(n.compare("abc9","abc10")<0);
        System.out.println(n.compare("abc12def5","abc12def34")<0);
        System.out.println(n.compare("abc12def34ghi","abc12def34ghi")==0);
        System.out.println(n.compare("abc012def","abc12def"));
    }

    private Pattern pattern = Pattern.compile("\\d+");

    public int compare(String s0, String s1)
    {
        // Early return for equal strings
        if (s0.equals(s1))
        {
            return 0;
        }

        Matcher matcher0 = pattern.matcher(s0);
        Matcher matcher1 = pattern.matcher(s1);

        int prevIndex = 0;
        int startIndex = 0;

        // Compare character sequences and numbers in the input strings
        // as long as numbers are found in both strings
        boolean found0 = false;
        boolean found1 = false;
        do
        {
            found0 = matcher0.find();
            found1 = matcher1.find();

            if (found0 && found1)
            {
                // Compute the segments of characters in both strings
                // that precede the next number
                startIndex = matcher0.start();
                String segment0 = s0.substring(prevIndex, startIndex);
                startIndex = matcher1.start();
                String segment1 = s1.substring(prevIndex, startIndex);
                prevIndex = matcher1.end();

                // If the numbers occur at different positions in
                // the strings, perform a simple string comparison
                if (segment0.length() != segment1.length())
                {
                    return segment0.compareTo(segment1);
                }
                else
                {
                    // If the numbers occur at the same positions,
                    // compare the preceding string segments
                    int result = segment0.compareTo(segment1);
                    if (result != 0)
                    {
                        return result;
                    }
                }

                // Found two numbers at the same position in the
                // strings, and the preceding string segments
                // are equal. Compare the numbers.
                int number0 = Integer.parseInt(matcher0.group());
                int number1 = Integer.parseInt(matcher1.group());
                if (number0 != number1)
                {
                    return number0 - number1;
                }
            }
        }
        while (found0 && found1);

        // Strings do not contain any (more) numbers, and no difference could
        // be found yet. Perform a simple string comparison
        return s0.compareTo(s1);
    }

}
 
Jo, zum Beispiel mit einer Regex, die abwechselnd Zahl-Strings und Nicht-Zahl-Strings liefert, damit man sich die indizes sparen und leichter vergleichen kann... Aber .... naja :roll:
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben