Buch Cover Buch Cover Buch Cover Buch Cover

Web-Code: - Webcode Help

Lexikografisch sortieren (Algorithmen)

Um eine lexikographische Ordnung von Wörtern zu erreichen, kann nicht einfach die triviale aufsteigende Sortierung einer Zeichentabelle durchgeführt werden.

Zum einen müssen große und kleine Buchstaben gleich behandelt werden, und zum anderen sollen Umlaute und Ligaturen (ß) nach ihren zugrunde liegenden Buchstaben einsortiert werden:


 
 A < a < AA < aa < AAb < Aachen < ...

 ... < aha < Ähre < Akne < ...

 ... < haschen < Häschen < hat < ...

 ... < Masse < Maße < Maßeinheit < ...

 ... < ZZ < zz 
 

Entwickeln Sie nach obigem Beispiel eine Funktion, die zwei gegebene Wörter miteinander vergleicht.

Tipp: Ein 'ä' wird wie ein 'a' sortiert, es sei denn, es gibt auch eine ansonsten identische Wortvariante mit einem 'a' an derselben Stelle. In einem solchen Fall wird das Wort mit Umlaut nach letzterem einsortiert. Analog verhält es sich mit den Groß- und Kleinbuchstaben. Mit Vorteil werden die Wörter zunächst in ihre lexikalische Grundform gebracht: nur Kleinbuchstaben, keine Umlaute [a statt ä], keine Ligaturen [ss statt ß], keine Satzzeichen [Leerschlag statt '.']. Stimmen die Grundformen nicht überein, so wird nach eben dieser Grundform sortiert.

Dateien:

2 Kommentare

Bitte melde dich an um einen Kommentar abzugeben

Kommentare (2)

gressly 6. Juli 2011 21:47   reply report
guggisberg
Wie wird die Java Lösung eingesetzt? Wie kann man die Klasse DeutscherLexer nutzen?

Der "deutsche Lexer" ist ein Beispiel eines Java-Comparators.
Er wird eingesetzt bei allen sort()- und search()-Funktionen, die als Argument einen Comparator verlangen.
Beispiele:
Arrays.binarySearch(array, from, to, comparator)
Arrays.sort(array, from, to, comparator)
guggisberg 9. Januar 2011 11:01   reply report
Wie wird die Java Lösung eingesetzt? Wie kann man die Klasse DeutscherLexer nutzen?

4 Lösung(en)

import java.util.Comparator;

/**
 * Sortiere Deutsch.
 * @author Philipp Gressly (phi AT gressly DOT ch)
 */
public class DeutscherLexer implements Comparator<String> {

    @Override
    public int compare(String s1, String s2) {
        String ersetzt1 = ersetze(s1);
        String ersetzt2 = ersetze(s2);
        int cmp = ersetzt1.compareTo(ersetzt2);
        if(0 != cmp)    {
          return cmp; }
        for(int i = 0; i < s1.toLowerCase().length(); i++) {
           char c1 = s1.toLowerCase().charAt(i);
           char c2 = s2.toLowerCase().charAt(i);     
           if(c1 != c2) {
             return compareChars(c1, c2);
           }
        }
        for(int i = 0; i < s1.length(); i++) {
            char c1 = s1.charAt(i);
            char c2 = s2.charAt(i);     
            if(c1 != c2) {
              return compareChars(c1, c2);
            }
         }
        return 0; }


    int compareChars(char c1, char c2) {
        if(istZiffer(c1)   && istZiffer(c2)  ) {
            return c1 - c2;    }
        if(isSpecial(c1)   && isSpecial(c2)  ) {
            return c1 - c2;  }
        if(isUpperCase(c1) && isUpperCase(c2)) {
            return c1 - c2; }
        if(isLowerCase(c1) && isLowerCase(c2)) {
            return c1 - c2;   }
        int t1 = typeOf(c1); // 1: upper, 2: lower, 3: special
        int t2 = typeOf(c2);
        return t1 - t2;    }

    
   boolean istZiffer(char c2) {
        return '0' <= c2 && c2 <= '9';  }

   /**
    * Zum Sortieren der Typen lowerCase, upperCase, special
    * @return 1: upper; 2: lower; 3: special; 4: ziffer
    */
    int typeOf(char c1) {
        if(isUpperCase(c1)) {
            return 1; }
        if(isLowerCase(c1)) {
            return 2; }
        if(istZiffer(c1)) {
            return 4;
        }
        return 3;  } // special = 3


    boolean isSpecial(char c) {
        return !isLowerCase(c) && !isUpperCase(c);  }


    boolean isUpperCase(char c) {
        return 'A' <= c && c <= 'Z';   }

    boolean isLowerCase(char c) {
        return 'a' <= c && c <= 'z';   }

    /**
     * Ersetze Sonderzeichen durch ihre Grundbuchstaben.
     * Z. B. wird aus "Häuschen" "Hauschen" und aus
     * "Maße" wird "Masse".
     */
    String ersetze(String original) {
      StringBuilder sb = new StringBuilder();
      for(char c : original.toCharArray()) {
        c = Character.toLowerCase(c);
        if('ä' == c) {
          sb.append("a");  }
        else if('ö' == c)  {
          sb.append("o");  }
        else if('ü' == c)  {
          sb.append("u");  }
        else if('ß' == c)  {
          sb.append("ss"); }
        else if(Character.isLetter(c)) {
          sb.append(c);    }
        else if(istZiffer(c)) {
          sb.append(c);
        }
      }
      return sb.toString();
    }

} // end of class DeutscherLexer
                
# Lexikallische Sortierung
# 1. Schritt alle Worte werden in eindeutige Kleinschreibweise formatiert
# 2. Aufbau einer Schlüssel --> Werte Struktur (assoziatives Array)
# Die Schlüssel sind die Worte in eindeutiger Kleinschreibweise
# Die Werte sind die original Worte
# 3. Schritt Sortieren der Schlüssel und dann Ausgabe der Werte

def eindeutigeSchreibweise(s):
    s1 = s.lower()
    s2 = ''
    for c in s1:
        if c == 'ä':
            s2 = s2 + 'a'
        else:
            if c == 'ö':
                s2 = s2 + 'o'
            else:
                if c == 'ü':
                    s2 = s2 + 'u'
                else:
                    if c == 'ß':
                        s2 = s2 + 'ss'
                    else:
                        s2 = s2 + c

    return s2

def lexikalSortieren(l):
    #Aufbau des assoziativen Array (dictionary)
    woerter ={}
    for w in l:
        s = eindeutigeSchreibweise(w)
        woerter[s]=w
    wlist = woerter.keys()
    wlist.sort()
    for wort in wlist:
        print woerter[wort]        

s = 'Häschen  hat  Masse A  a so macht das kein Sinn Maßeinheit ZZ Top AA aa AAb  Aachen aha  Ähre  Akne haschen  Maße '
l = s.split()
lexikalSortieren(l)
                

Lösung von: Martin Guggisberg (Universität Basel / PH FHNW)

/*****************************************************************************\
| In JavaScript wäre das die einfache anweisung
>>>>
> Array.sort(String1.localeCompare(String2));
>>>>
| respektive:
>>>>
> Array.sort(String1.localeCompare(String2, "de",
>   {sensitivity: case, ignorePunctuation: true, caseFirst: upper }));
>>>>
| um die deutsche lexikographie zu erzwingen.
| Hier aber die harte tour.
\*****************************************************************************/


function compareLemmas_de(lem1, lem2) {
  var comp1, comp2,
      i = 0;

  function prepare(str) {
    str = str.toLowerCase();                // kleinbuchstaben
    str = str.replace(/ä/g, "a");
    str = str.replace(/ö/g, "o");
    str = str.replace(/ü/g, "u");
    str = str.replace(/ß/g, "s");
    str = str.replace(/(\.)|( )|(-)/g, ""); // punkt, leerzeichen, bindestrich
    return str;
  }

  function isUpperCase(char) { return char == char.toLowerCase(); }

  function isSpecialChar(char) {
    return char == "Ä" || "ä" || "Ö" || "ö" || "Ü" || "ü" || "ß";
  }

  var comp1 = prepare(lem1), comp2 = prepare(lem2);
  if (comp1 > comp2) return 1;
  if (comp1 < comp2) return -1;

  if (comp1 == comp2) {
    while(i < Math.min(lem1.length, lem2.length)) {
      if (
        (isUpperCase(lem1[i]) && !isUpperCase(lem2[i])) ||    // A > a
        (isSpecialChar(lem1[i]) && !isSpecialChar(lem2[i]))   // a > ä
      ) return 1;
      else if (
        (!isUpperCase(lem1[i]) && isUpperCase(lem2[i])) ||    // a < A
        (!isSpecialChar(lem1[i]) && isSpecialChar(lem2[i]))   // ä < a
      ) return -1;
      i++;
    }
    // nach der while-schleife: das längere wort wird nachsortiert
    if (lem1.length > lem2.length) return -1;
    else if (lem1.length < lem2.length) return 1;
    // und schließlich:
    return 0;   // falls keine unterscheidung zwischen A/a oder a/ä möglich
  }
}

var wordList = ("A,hat,Masse,A.A.,AAA,Achter,Häschen,Aal,hält,Menschenskind," +
  "AAb,RE44,Ähre,RE - 44,re,re44,massieren,A. Hauser,RE43,RE - 43,re43,Akne," +
  "H. Aschen,Masseur,Ahoi,RE34,RE - 34,re34,Weinflasche,Aachen,achter,Mist," +
  "a,Maß,aha,AA,ZZ,haschen,zz,Maßeinheit,aa").split(",");

wordlist.sort(compareLemmas_de);
document.write(wordList.join(" > "));                      // lissalanda@gmx.at

                

Lösung von: Lisa Salander (Heidi-Klum-Gymnasium Bottrop)

public class Main {

    public static void main(String[] args) {
        List<String> words = new ArrayList<>();

        words.add("A");
        words.add("hat");
        words.add("Masse");
        words.add("A.A.");
        words.add("AAA");
        words.add("Achter");
        words.add("Häschen");
        words.add("Aal");
        words.add("hält");
        words.add("Menschenskind");
        words.add("AAb");
        words.add("RE44");
        words.add("Ähre");
        words.add("RE - 44");
        words.add("re");
        words.add("re44");
        words.add("massieren");
        words.add("A. Hauserv");
        words.add("RE43");
        words.add("RE - 43");
        words.add("re43");
        words.add("Akne");
        words.add("H. Aschen");
        words.add("Masseur");
        words.add("Ahoi");
        words.add("RE34");
        words.add("RE - 34");
        words.add("re34");
        words.add("Weinflasche");
        words.add("Aachen");
        words.add("achter");
        words.add("Mist");
        words.add("a");
        words.add("Maß (und no a Maß)");
        words.add("aha");
        words.add("AA");
        words.add("ZZ");
        words.add("haschen");
        words.add("zz");
        words.add("Maßeinheit");
        words.add("aa");

        new Main().sort(words);
    }

    private void sort(List<String> words) {
        words.sort(new Sort());
        words.forEach(System.out::println);
    }

    private static class Sort implements Comparator<String> {

        @Override
        public int compare(String s1, String s2) {
            s1 = init(s1);
            s2 = init(s2);

            for(char c1 : s1.toCharArray()) {
                for(char c2 : s2.toCharArray()) {
                    if(c1 < c2) {
                        return -1;
                    } else if(c1 > c2) {
                        return 1;
                    }
                }
            }

            return 0;
        }

        private String init(String s) {
            return s.toLowerCase().replace("ä", "a")
                    .replace("ö", "o")
                    .replace("ü", "u")
                    .replace("ß", "ss")
                    .replace(".", "")
                    .replace("-", "");
        }
    }
}
                

Lösung von: Name nicht veröffentlicht

Verifikation/Checksumme:

Beispiele von Grundformen:

  • Schweiz -> schweiz
  • für -> fur
  • Öl -> ol
  • Maße -> masse

Aktionen

Bewertung

Durchschnittliche Bewertung:

Eigene Bewertung:
Bitte zuerst anmelden

Meta

Zeit: 2-4
Schwierigkeit: k.A.
Webcode: t42p-7sny
Autor: Philipp G. Freimann (BBW (Berufsbildungsschule Winterthur) https://www.bbw.ch)

Download PDF

Download ZIP

Zu Aufgabenblatt hinzufügen