PeTahGeh: Einen String "entbuchstabisieren"

Moin moin,
hab da mal ne Frage: Gibt es eine einfache PHP-Funktion, die mir aus einem String die Buchstaben holt und daraus 2-stellige Zahlen macht?

Hintergrund: Ich habe eine Artikelnummer aus einer externen Quelle, die  einen 7- oder 8-stelligen Mischmasch (z.B.: '54R7A2Z') hat und würde daraus gerne einen reinen Zahlen-String bauen, in dem alle Buchstaben zu 2-stelligen Zahlen gewandelt werden, damit es in unsere WWS-DB passt.

Ich wäre froh über ein paar Lösungsansätze, weil ich dazu noch nichts konkretes, das "grösseren" Programmieraufwand erfordern würde. Ich würde es gern sleak und kurz halten.

Vielen Dank schonmal im Voraus, Peter

  1. hi,

    hab da mal ne Frage: Gibt es eine einfache PHP-Funktion, die mir aus einem String die Buchstaben holt und daraus 2-stellige Zahlen macht?

    Was glaubst du - ist das eine Standard-Aufgabe, die täglich zigfach zu bewältigen ist, und deshalb eine eigene native Funktion rechtfertigt ...?

    Hintergrund: Ich habe eine Artikelnummer aus einer externen Quelle, die  einen 7- oder 8-stelligen Mischmasch (z.B.: '54R7A2Z') hat und würde daraus gerne einen reinen Zahlen-String bauen, in dem alle Buchstaben zu 2-stelligen Zahlen gewandelt werden, damit es in unsere WWS-DB passt.

    Und nach welcher Umwandlungsvorschrift?

    Ich wäre froh über ein paar Lösungsansätze, weil ich dazu noch nichts konkretes, das "grösseren" Programmieraufwand erfordern würde.

    Indexbasierten Zugriff auf Zeichen in Strings erklärt das Manual, und die Ersetzungen liessen sich ja bspw. in einem Array mit den Buchstaben als Schlüssel ablegen ...

    Ich würde es gern sleak und kurz halten.

    Ich finds immer groovy, wenn die Leute ihre Buzzwords schon vor dem Programmieren lernen.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. hab da mal ne Frage: Gibt es eine einfache PHP-Funktion, die mir aus einem String die Buchstaben holt und daraus 2-stellige Zahlen macht?
      Was glaubst du - ist das eine Standard-Aufgabe, die täglich zigfach zu bewältigen ist, und deshalb eine eigene native Funktion rechtfertigt ...?

      Auf jeden Fall. Ich bin bestimmt nicht der erste, der sich damit auseinandersetzen muss. Die Migration von DB-Feldern wird doch erst nicht seit gestern gemacht ^^

      Hintergrund: Ich habe eine Artikelnummer aus einer externen Quelle, die  einen 7- oder 8-stelligen Mischmasch (z.B.: '54R7A2Z') hat und würde daraus gerne einen reinen Zahlen-String bauen, in dem alle Buchstaben zu 2-stelligen Zahlen gewandelt werden, damit es in unsere WWS-DB passt.
      Und nach welcher Umwandlungsvorschrift?

      Zahlen bleiben Zahlen und die Buchstaben kriegen eine 2-stelligen Zahl. Ihre Position im Alphabet z.B.

      Ich wäre froh über ein paar Lösungsansätze, weil ich dazu noch nichts konkretes, das "grösseren" Programmieraufwand erfordern würde.
      Indexbasierten Zugriff auf Zeichen in Strings erklärt das Manual, und die Ersetzungen liessen sich ja bspw. in einem Array mit den Buchstaben als Schlüssel ablegen ...

      Danke, so könnte man es machen. Bin halt ein PHP-Anfänger mit wenig Zeit.

      Ich würde es gern sleak und kurz halten.
      Ich finds immer groovy, wenn die Leute ihre Buzzwords schon vor dem Programmieren lernen.

      Uhh, wie sophisticated deine letzte phrase klingt *zwinker*

      gruß,
      wahsaga

      gruss, peter

      1. Hi,

        Hintergrund: Ich habe eine Artikelnummer aus einer externen Quelle, die  einen 7- oder 8-stelligen Mischmasch (z.B.: '54R7A2Z') hat und würde daraus gerne einen reinen Zahlen-String bauen, in dem alle Buchstaben zu 2-stelligen Zahlen gewandelt werden, damit es in unsere WWS-DB passt.
        Und nach welcher Umwandlungsvorschrift?
        Zahlen bleiben Zahlen und die Buchstaben kriegen eine 2-stelligen Zahl. Ihre Position im Alphabet z.B.

        Das macht so keinen Sinn, wenn du von dem neuen String (mit nur Zahlen) wieder auf die Artikelnummer schliessen willst.

        Beispiel:
        Artikelnummer:  A01
        Dein Ergebnis:  0101

        Vielleicht waere es fuer dich eine moeglichkeit, alle Zeichen in ihren ASCII-Code umzuwandeln. Dafuer gibt es sicher schon vorgefertigte Funktionen von PHP.

        mfG,
        steckl

        1. Moin moin,

          Zahlen bleiben Zahlen und die Buchstaben kriegen eine 2-stelligen Zahl. Ihre Position im Alphabet z.B.

          Das macht so keinen Sinn, wenn du von dem neuen String (mit nur Zahlen) wieder auf die Artikelnummer schliessen willst.

          Beispiel:
          Artikelnummer:  A01
          Dein Ergebnis:  0101

          Vielleicht waere es fuer dich eine moeglichkeit, alle Zeichen in ihren ASCII-Code umzuwandeln. Dafuer gibt es sicher schon vorgefertigte Funktionen von PHP.

          Und genauso hab ich das auch gemacht, ihr habt mich auf den richigen Weg geführt, danke nochmal! :)

          vielleicht nicht gerade die schlankeste lösung, aber es funktioniert (temp_ses[4] ist hierbei der zu bearbeitende String):

          $temp_artikelnummer = '';
             for ($op=0;$op < strlen($temp_ses[4]);$op++) {
              $temp_char_ascii = ord(substr($temp_ses[4],$op,1));
              $temp_char_nonascii = substr($temp_ses[4],$op,1);
               if ($temp_char_ascii < 65 || $temp_char_ascii > 90) {
                 $temp_artikelnummer .= $temp_char_nonascii;
               } else {
                 $temp_artikelnummer .= $temp_char_ascii;
               }
          }

          gruss, peter

          1. Hi,

            Zahlen bleiben Zahlen und die Buchstaben kriegen eine 2-stelligen Zahl. Ihre Position im Alphabet z.B.

            Das macht so keinen Sinn, wenn du von dem neuen String (mit nur Zahlen) wieder auf die Artikelnummer schliessen willst.

            Beispiel:
            Artikelnummer:  A01
            Dein Ergebnis:  0101

            Vielleicht waere es fuer dich eine moeglichkeit, alle Zeichen in ihren ASCII-Code umzuwandeln. Dafuer gibt es sicher schon vorgefertigte Funktionen von PHP.

            Und genauso hab ich das auch gemacht, ihr habt mich auf den richigen Weg geführt, danke nochmal! :)

            Falsch, du wandelst nur Grossbuchstaben in ASCII-Code um und nicht ALLE zeichen.

            vielleicht nicht gerade die schlankeste lösung, aber es funktioniert (temp_ses[4] ist hierbei der zu bearbeitende String):

            $temp_artikelnummer = '';
               for ($op=0;$op < strlen($temp_ses[4]);$op++) {
                $temp_char_ascii = ord(substr($temp_ses[4],$op,1));
                $temp_char_nonascii = substr($temp_ses[4],$op,1);
                 if ($temp_char_ascii < 65 || $temp_char_ascii > 90) {
                   $temp_artikelnummer .= $temp_char_nonascii;
                 } else {
                   $temp_artikelnummer .= $temp_char_ascii;
                 }
            }

            Da ich kein PHP kann hoffe ich deinen Code richtig zu interpretieren.
            Wenn das aktuelle Zeichen ein Grossbuchstabe ist haengst du an den Ergebnisstring dessen ASCII-Code an, wenn es eine Zahl ist haengst du diese Zahl direkt an (und nicht deren ASCII-Code).

            Also waere das Ergebnis bei einer Artikelnummer von "AAA" und "656565" immer das gleiche. Du muesstest also Ziffern auch in ASCII-Code umwandeln.

            Ein weiteres Problem tritt auf, wenn die Artikelnummer einen Kleinbuchstaben enthaelt. Ich weiss nicht, ob das moeglich ist, aber wenn musst du diese ebenfalls irgendwie behandeln. Momentan wuerdest du versuchen, sie ohne Umwandlung in die DB zu schreiben. Hierbei ist ein Problem, dass der ASCII-Code auch 3-Stellig sein kann (beispiel: x = 120).

            mfG,
            steckl

  2. Hallo Peter,

    Hintergrund: Ich habe eine Artikelnummer aus einer externen Quelle, die  einen 7- oder 8-stelligen Mischmasch (z.B.: '54R7A2Z') hat und würde daraus gerne einen reinen Zahlen-String bauen, in dem alle Buchstaben zu 2-stelligen Zahlen gewandelt werden, damit es in unsere WWS-DB passt.

    Ich wäre froh über ein paar Lösungsansätze,

    Naja, da Du PHP als Thema gewählt hast, gehe ich mal davon aus, dass Du PHP haben willst. Wie andere hier im Thread schon angedeutet haben, ist es nicht ideal, jeden Buchstaben einfach nur in zwei Ziffern zu verwandeln - dann würdest Du Dopplungen kommen, was nicht so toll ist.

    Ein brauchbarer Ansatz ist, die Buchstaben/Ziffernkombination der Artikelnummer als Zahl selbst zu betrachten - und zwar im 36er-System, d.h. jede Stelle hat 36 mögliche Werte (10 Ziffern, 26 Buchstaben). Das heißt: eine Ziffer 0 wäre 0 wert, eine Ziffer 1 wäre 1 wert, etc. Ein Buchstabe 'A' wäre 10 wert, ein Buchstabe 'B' 11, eine Buchstabe 'Z' 35. Damit würdest Du z.B. bei einer Zeichenfolge 'A4' folgende Situation haben: Höherwertige Stelle ist 'A', das ist 10 wert, d.h. 10 bei Wertigkeit 1. Niederwertige Stelle ist '4', das ist 4 wert, d.h. 4 bei Wertigkeit 0. Damit hast Du: Zahl = 10 * 36^1 + 4 * 36^0 = 10 * 36 + 4 = 364. Genauso lässt sich jede andere beliebige Zeichenfolge umwandeln.

    Du bekommst mit diesem Ansatz jedoch wieder ein Problem: PHP kann zumindest auf 32bit-Systemen nur begrenzt gut mit großen Ganzzahlen umgehen - es gibt irgendwo ein Limit. Bei Deinem Beispiel '54R7A2Z' stößt Du mit meinem vorgeschlagenen System gerade schon ans Limit - da klappt die Umwandlung allerdings selbst noch - die Rückumwandlung versagt bereits. Bei einer Stelle mehr kann es sein, dass sogar die Umwandlung versagt, ein Beispiel für so eine Nummer wäre 'XX4R7A2Z'. Daher musst Du - wenn Du PHP verwenden willst - auf die Funktionen zur Rechnung mit beliebiger Genauigkeit zurückgreifen - die sind etwas langsamer, dafür bekommst Du garantiert eine korrekte Zahl (im Zehnersystem dargestellt).

    Beachte jedoch, dass das Problem, das PHP mit den Zahlen hat, unter Umständen auch Deine Datenbank treffen könnte - es hängt davon ab, wie die Spalte dort definiert ist. Mein Beispiel 'XX4R7A2Z' würde nach der oben angegebenen Umwandlungsslogik zur Zahl 2658138786251 verwandelt werden - die hat 12 Stellen! Andererseits ist das von mir vorgestellte Verfahren das kompakteste, das es ermöglicht, die Anforderungen zu erfüllen, sofern eine beliebige (!) Kombination von beliebigen (!) Ziffern und Buchstaben erlaubt ist. Falls es bestimmte Regeln gibt, nach denen sich die bisherige Artikelnummer verhält, dann könnte man das Verfahren optimieren - d.h. wenn man z.B. wüßte, dass die Stellen 1-2 immer Zahlen sind und 3-8 immer Buchstaben (oder so ähnlich), dann könnte man nicht immer fest ins 36er-System umrechnen, sondern in ein gemischtes System, was dann Platz im Zahlenraum sparen würde. Wenn keinerlei Schema für die Artikelnummern bekannt ist, dann muss die Datenbank halt schlicht eine genügend große Spalte haben.

    Ich habe Dir mal zwei funktionieren vorprogrammiert, die nach dem von mir beschriebenem Schema arbeiten. Die eine konvertiert Deine Buchstabenfolge in eine Zahl, die andere macht das gleiche wieder rückgängig. Diese Funktionen sollen demonstrieren, wie so ein Problem angegangen werden kann.

    <?php  
      
    // Konvertiert eine Zeichenkette, die aus Buchstaben A-Z und Ziffern 0-9 besteht  
    // in eine Zahl. Dabei wird jedes Zeichen als eine Ziffer im 36er-System betrachtet  
    // Die höherwertigste Ziffer kommt zuerst  
    function buchstabenZuZahl ($string) {  
        // hilfsvariablen definieren: kleinst- und größtmöglicher buchstabe  
        static $A = 65; // ASCII 'A'  
        static $Z = 90; // ASCII 'Z'  
        // hilfsvariablen: kleinst- und größtmögliche ziffer  
        static $_0 = 48; // ASCII '0'  
        static $_9 = 57; // ASCII '9'  
        // Endergebnis vormerken  
        $resultat = '0';  
        // String in Grossbuchstaben verwandeln  
        // (dann erschlagen wir auch kleinbuchstaben)  
        $string = strtoupper ($string);  
        // bestimmte die länge der zeichenkette  
        $laenge = strlen ($string);  
        // gehe die zeichenkette zeichen für zeichen durch  
        for ($i = 0; $i < $laenge; $i++) {  
            // multipliziere das resultat mit 36, um eine  
            // stelle vorzurücken. Das sollte zwar im ersten  
            // Schleifendurchgang nicht durchgeführt werden,  
            // allerdings ist dort das Resultat bereits 0,  
            // sprich: die Multiplikation ändert nichts  
            $resultat = bcmul ($resultat, 36);  
            // hole das aktuelle zeichen aus der zeichenkette  
            $code = ord ($string[$i]);  
            // haben wir ein ziffer  
            if ($code >= $_0 and $code <= $_9) {  
                // ord ('0') 48, d.h. wenn eine '0' vorkommt,  
                // dann steht hier 48 - 48 = 0, wenn eine '1'  
                // vorkommt, steht hier 49 - 48 = 1, usw. usf.  
                $resultat = bcadd($resultat, $code - $_0);  
            } else if ($code >= $A and $code <= $Z) {  
                // ord ('A') = 65, d.h. wenn ein 'A' vorkommt,  
                // dann steht hier 65 - 65 + 10 = 10, wenn hier  
                // ein Z vorkommt, dann steht hier 90 - 65 + 10 = 35  
                // usw.,usf.  
                $resultat = bcadd ($resultat, $code - $A + 10);  
            } else {  
                // unbekanntes zeichen, ignoriere es  
            }  
        }  
        // gebe das resultat zurück  
        return $resultat;  
    }  
      
    // Konvertiere eine Zahl an Hand der obigen Regel zurück in eine Zeichenkette  
    function zahlZuBuchstaben ($zahl) {  
        // hilfsvariablen definieren: 'A' und '0'  
        static $A = 65; // ASCII 'A'  
        static $_0 = 48; // ASCII '0'  
        // ergebnisstring merken  
        $resultat = '';  
        // nimm den betrag der zahl, sicherheitshalber  
        $zahl = bcmul ($zahl, bccomp ($zahl, 0, 0), 0);  
        // falls die zahl 0 ist, ist die darstellung trivial  
        if (!$zahl) {  
            return '0';  
        }  
        // solange die zahl > 0 ist: füge eine stelle hinzu  
        while ($zahl > 0) {  
            // den 36er-Rest der Zahl holen  
            $rest = bcmod ($zahl, 36);  
            // die Zahl durch 36 Teilen (Integer-Division)  
            // damit bleiben keine Komma-Stellen übrig  
            $zahl = bcdiv ($zahl, 36, 0);  
            // wenn der rest >= 10 ist, wird's ein Buchstabe  
            if ($rest >= 10) {  
                $resultat .= chr ($rest + $A - 10);  
            } else {  
                // es wird ne ziffer  
                $resultat .= chr ($rest + $_0);  
            }  
        }  
        // das problem bleibt jetzt nur, dass $resultat in der  
        // falschen reihenfolge zusammengebaut wurde, daher  
        // muss die zeichenkette noch umgedreht werden  
        return strrev ($resultat);  
    }  
      
    ?>
    

    Viele Grüße,
    Christian

    1. Hallo Peter,

      Hintergrund: Ich habe eine Artikelnummer aus einer externen Quelle, die  einen 7- oder 8-stelligen Mischmasch (z.B.: '54R7A2Z') hat und würde daraus gerne einen reinen Zahlen-String bauen, in dem alle Buchstaben zu 2-stelligen Zahlen gewandelt werden, damit es in unsere WWS-DB passt.

      Ich wäre froh über ein paar Lösungsansätze,

      Naja, da Du PHP als Thema gewählt hast, gehe ich mal davon aus, dass Du PHP haben willst. Wie andere hier im Thread schon angedeutet haben, ist es nicht ideal, jeden Buchstaben einfach nur in zwei Ziffern zu verwandeln - dann würdest Du Dopplungen kommen, was nicht so toll ist.

      Ein brauchbarer Ansatz ist, die Buchstaben/Ziffernkombination der Artikelnummer als Zahl selbst zu betrachten - und zwar im 36er-System, d.h. jede Stelle hat 36 mögliche Werte (10 Ziffern, 26 Buchstaben). Das heißt: eine Ziffer 0 wäre 0 wert, eine Ziffer 1 wäre 1 wert, etc. Ein Buchstabe 'A' wäre 10 wert, ein Buchstabe 'B' 11, eine Buchstabe 'Z' 35. Damit würdest Du z.B. bei einer Zeichenfolge 'A4' folgende Situation haben: Höherwertige Stelle ist 'A', das ist 10 wert, d.h. 10 bei Wertigkeit 1. Niederwertige Stelle ist '4', das ist 4 wert, d.h. 4 bei Wertigkeit 0. Damit hast Du: Zahl = 10 * 36^1 + 4 * 36^0 = 10 * 36 + 4 = 364. Genauso lässt sich jede andere beliebige Zeichenfolge umwandeln.

      Du bekommst mit diesem Ansatz jedoch wieder ein Problem: PHP kann zumindest auf 32bit-Systemen nur begrenzt gut mit großen Ganzzahlen umgehen - es gibt irgendwo ein Limit. Bei Deinem Beispiel '54R7A2Z' stößt Du mit meinem vorgeschlagenen System gerade schon ans Limit - da klappt die Umwandlung allerdings selbst noch - die Rückumwandlung versagt bereits. Bei einer Stelle mehr kann es sein, dass sogar die Umwandlung versagt, ein Beispiel für so eine Nummer wäre 'XX4R7A2Z'. Daher musst Du - wenn Du PHP verwenden willst - auf die Funktionen zur Rechnung mit beliebiger Genauigkeit zurückgreifen - die sind etwas langsamer, dafür bekommst Du garantiert eine korrekte Zahl (im Zehnersystem dargestellt).

      Beachte jedoch, dass das Problem, das PHP mit den Zahlen hat, unter Umständen auch Deine Datenbank treffen könnte - es hängt davon ab, wie die Spalte dort definiert ist. Mein Beispiel 'XX4R7A2Z' würde nach der oben angegebenen Umwandlungsslogik zur Zahl 2658138786251 verwandelt werden - die hat 12 Stellen! Andererseits ist das von mir vorgestellte Verfahren das kompakteste, das es ermöglicht, die Anforderungen zu erfüllen, sofern eine beliebige (!) Kombination von beliebigen (!) Ziffern und Buchstaben erlaubt ist. Falls es bestimmte Regeln gibt, nach denen sich die bisherige Artikelnummer verhält, dann könnte man das Verfahren optimieren - d.h. wenn man z.B. wüßte, dass die Stellen 1-2 immer Zahlen sind und 3-8 immer Buchstaben (oder so ähnlich), dann könnte man nicht immer fest ins 36er-System umrechnen, sondern in ein gemischtes System, was dann Platz im Zahlenraum sparen würde. Wenn keinerlei Schema für die Artikelnummern bekannt ist, dann muss die Datenbank halt schlicht eine genügend große Spalte haben.

      Ich habe Dir mal zwei funktionieren vorprogrammiert, die nach dem von mir beschriebenem Schema arbeiten. Die eine konvertiert Deine Buchstabenfolge in eine Zahl, die andere macht das gleiche wieder rückgängig. Diese Funktionen sollen demonstrieren, wie so ein Problem angegangen werden kann.

      <?php ..... ?>

      Viele Grüße,
      Christian

      Hi Christian,
      danke für die ausführliche Antwort, aber die neue Artikelnummer darf ein String sein und wird einfach nur in einem DB-Feld abgelegt. Aber die vielen Befehle, die ich aus deinem Code gelernt habe werden mir auch in meinen anderen Problemen sicher weiterhelfen.

      Gruss, peter