Straße und Hausnummer trennen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Straße und Hausnummer trennen

    Hallo zusammen,

    ich habe eine Datenbank, in der Straße und Hausnummer in einem Feld stehen. Diese sollen aber nun getrennt werden.

    Will mein Glück mit strpos() versuchen, aber hier kann ich ja nur explizit ein Zeichen angeben. Es müsste also die Position des ersten numerischen Vorkommens abgefragt werden. Gibt es hierzu irgend eine strpos-variante die RegExp versteht oder wie könnte man das lösen?

    Alle Ziffern prüfen, in ein Array ziehen und dann nach Position sortieren?
    Gibt's ne elegantere Lösung?

    Danke,
    Andi

  • #2
    Also ich habe mir jetzt mal was zusammengebastelt, was erst mal funktioniert:

    PHP-Code:
    if(ereg("0"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "0");}
    if(
    ereg("1"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "1");}
    if(
    ereg("2"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "2");}
    if(
    ereg("3"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "3");}
    if(
    ereg("4"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "4");}
    if(
    ereg("5"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "5");}
    if(
    ereg("6"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "6");}
    if(
    ereg("7"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "7");}
    if(
    ereg("8"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "8");}
    if(
    ereg("9"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "9");}
    asort($str_pos);

    $x=1;
    foreach (
    $str_pos as $key => $val) {
        if(
    $x == 1){$my_str_pos $val;}
        
    $x++;
    }

    $form_str trim(substr($user['strasse'], 0$my_str_pos));
    $form_strnr trim(substr($user['strasse'], $my_str_pos)); 
    Vielleicht geht es irgendwie schicker und kürzer.

    Ein Problem gibt es jedoch mit ausländischen Adressen, da diese oftmals die Hausnummer vorne stehen haben.
    Z.B. "123 Main Street".

    Dafür müsste dann noch ne Abfrage rein wenn der String Numerisch beginnt, dass dann die Nummer am Anfang abgegriffen wird.
    Problematisch wird es aber dann, wenn er hier ggf. auch Alphanumerische Hausnumern gibt.
    Z.B. "123 B Main Street".

    Kommentar


    • #3
      Hi,

      du suchst:

      SQL Substring - 1Keydata SQL-Tutorial

      aber du hast prinzipiell nen falschen Datenbank Aufbau, wenn alles in einer Zelle steht!

      mfg streuner
      Erst wenn der letzte FTP Server kostenpflichtig, der letzte GNU-Sourcecode verkauft, der letzte Algorithmus patentiert,
      der letzte Netzknoten verkommerzialisert ist, werdet Ihr merken, dass Geld nicht von alleine programmiert.

      "Diese Software verdient die 3 großen GGG: --- Gesehen --- Gelacht --- Gelöscht ---"

      Kommentar


      • #4
        Danke, aber nein, substr() suche ich nicht.
        substr() auf sql-basis löst auch nicht das Problem zum Ermitteln der ersten numerischen Stelle.

        Ausserdem geht es hier gar nicht um SQL speziell!
        Die Daten werden mir als Excel-Liste zur Verfügung gestellt und ich muss sie für eine Anwendung säubern.
        Ich importiere die zwar in eine SQL-Datenbank, aber dass ist nicht der Kern der Problems.

        Danke,
        Andi

        Kommentar


        • #5
          Haußnummer und Straßennamen automatisiert zu trennen ist höchst komplex und aufwändig. Beispiele von gültigen Straßennamen/Hausnummern:

          Straße des 17. Juni 16 (Straße: Straße des 17. Juni, Hausnummer: 16)
          Musterstraße 22 TOP 4 (Straße: Musterstraße, Hausnummer: 22 TOP 4)
          12. Februar-Platz 1A (Straße: 12. Februar-Platz, Hausnummer: 1A)
          164er Ring 3 (Straße: 164er Ring, Hausnummer: 3)

          Und das sind jetzt nur mal deutschsprachige Adressen.

          Ich würde die einfachen Adressen (also [A-Za-z]+\s[0-9]+) automatisiert verarbeiten und beim Rest muss halt jemand per Hand nacharbeiten. So hält man den Aufwand in Grenzen.

          Kommentar


          • #6
            Zitat von h3ll Beitrag anzeigen
            ...
            Musterstraße 22 TOP 4 (Straße: Musterstraße, Hausnummer: 22 TOP 4)
            ...
            Interessant, kann man irgendwo nachlesen, wo diese Notation eingesetzt wird und was sie bedeutet?

            Zitat von andik2000 Beitrag anzeigen
            Hallo zusammen,

            ich habe eine Datenbank, in der Straße und Hausnummer in einem Feld stehen. Diese sollen aber nun getrennt werden.
            Die wichtigste Frage dabei ist:
            WARUM trennen?

            Hausnummern in Adressangaben sind sehr fragile Objekte. Auch wenn du glaubst, schon alle Variationen gesehen zu haben, es gibt immer welche, die du noch nicht gesehen hast.

            Es müsste also die Position des ersten numerischen Vorkommens abgefragt werden.
            Nein: Wie h3ll schon aufführte, gibt es Straßennamen, die selbst Ziffern enthalten.
            * Darüber hinaus gibt es Anschriften ganz ohne Hausnummern.
            * Es gibt kombinierte Hausnummern (08/15) und Von-Bis-Hausnummern (23-42).
            * Es gibt Adressangaben, da folgen auf die Hausnummer weitere Angaben (Treppenhaus-, Stockwerksnummer, e.t.c.)
            * ...

            Gibt es hierzu irgend eine strpos-variante die RegExp versteht ...?
            Die strpos()-"Variante", die reguläre Ausdrücke versteht, heißt preg_match($pcre, $haystack, $hits, PREG_OFFSET_CAPTURE). Allerdings brauchst du bei der Benutzung von preg_match() in deinem Fall keine Positionsangaben mehr. Wenn du den richtigen Regex benutzt, liefert dir $hits alle gewünschten Bestandteile als Subpatterns ins Haus[0].

            Zitat von andik2000 Beitrag anzeigen
            Also ich habe mir jetzt mal was zusammengebastelt, was erst mal funktioniert:

            PHP-Code:
            if(ereg("0"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "0");}
            if(
            ereg("1"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "1");}
            // 7x der gleiche Unfug
            if(ereg("9"$user['strasse'])){$str_pos[] = strpos($user['strasse'], "9");}
            asort($str_pos);

            $x=1;
            foreach (
            $str_pos as $key => $val) {
                if(
            $x == 1){$my_str_pos $val;}
                
            $x++;
            }

            $form_str trim(substr($user['strasse'], 0$my_str_pos));
            $form_strnr trim(substr($user['strasse'], $my_str_pos)); 
            Vielleicht geht es irgendwie schicker und kürzer.
            Wie kommt man auf so ein umständliches Konstrukt? Wenn du schon reguläre Ausdrücke benutzt, dann frage nicht in jede Ziffer einzeln ab. Die Dinger sind sehr leistungsfähig und können das auch allein.

            PHP-Code:
            $pcre '/\A\s*
                (.*?) # strasze
                \s*
                \x2f? # slash, siehe forum.jtl-software.de
                (
                    \pN+\s*[a-zA-Z]? # nummer + buchstabe
                    (?:\s*[-\x2f\pP]\s*\pN+\s*[a-zA-Z]?)* # von-bis + zick-zack
                ) # hausnummer
                \s*\z/ux'
            ;

            preg_match($pcre$address_de_only$h); 
            Das sollte dir für deutsche Adressangaben in $h ein Array wie folgendes liefern:
            Code:
            array (
                0 => 'Große Heimstraße 2½', // beides zusammen
                1 => 'Große Heimstraße', // Straßenname
                2 => '2½', // "Hausnummer"
            )
            Falls nicht, hat die angegebene Adresse keine Hausnummer oder wurde durch den Regex nicht erfasst (dann verschicke halt keine Post nach Mannheim ).

            *update*

            Hier noch das verwendete (und sicher unvollständige) Test-Array:
            PHP-Code:
            $tests = array (
                
            // works
                
            'Große Heimstraße 2',
                
            'Große Heimstraße 2½',
                
            'Stockumer Straße 398 – 398½ - 402',
                
            'Mariahilfer Straße 38–48',
                
            'Irgendwo in Berlin linear 08-15',
                
            'Irgendwo in Berlin zick/zack 08/15',
                
            '7. Straße des 1. April 5',

                
            // needs enhancement
                
            'A1 1'// Landgericht Mannheim?
                
            'A 1 1'// Landgericht Mannheim?

                // does not work (obviously)
                
            '5th Avenue',
            ); 
            Bevor jetzt also noch wer auf die Idee kommt, eine ausgeklügelte strr?pos()-substr()-Logik zu posten: Erstmal testen, ob die wenigstens mit dieser Liste zurechtkommt.

            *end_update*

            Ein Problem gibt es jedoch mit ausländischen Adressen, da diese oftmals die Hausnummer vorne stehen haben.
            Z.B. "123 Main Street".
            Musst du Adressen außerhalb des deutschen Sprachraums erfassen? Falls ja, kommen wir wieder zu meiner ersten Frage: Warum (zum Geier) willst du die Hausnummer abtrennen?

            Dafür müsste dann noch ne Abfrage rein wenn der String Numerisch beginnt, dass dann die Nummer am Anfang abgegriffen wird.
            Ja und du brauchst eine künstliche Intelligenz, die (wie ein Mensch auf den ersten Blick) erkennt, ob es sich jetzt um eine Adresse mit Hausnummer vorn oder hinten handelt oder ob die Zifferngruppe zum Straßennamen gehört. Prinzipiell könnte man natürlich Fallunterscheidungen je nach Land machen. ... und dabei Belgien nicht vergessen, wo schon mal bei zweisprachig angegebenen Adressen die Hausnummer in der Mitte steht ...

            Problematisch wird es aber dann, wenn er hier ggf. auch Alphanumerische Hausnumern gibt.
            Z.B. "123 B Main Street".
            Das wäre für einen Regex das geringste Problem, weil es für so etwas Zeichenklassen gibt.

            Gibt's ne elegantere Lösung?
            Ja, die Gültigkeit der Adresse bei einem entsprechenden Dienstleister abfragen. Am besten bei dem, der auch die Päckchen und Briefe zustellt, die dein Brötchengeber verschickt. Denn so ein Dienstleister (im Volkmund auch "Post" genannt) hat jahrhundertelange Erfahrung im Umgang mit Adressangaben.

            --
            [0] pun intended.
            Zuletzt geändert von fireweasel; 13.09.2013, 13:49. Grund: PCRE mit mehr Kommentaren, Test-Array
            Klingon function calls do not have “parameters”‒they have “arguments”‒and they always win them!

            Kommentar


            • #7
              Zitat von fireweasel Beitrag anzeigen
              Interessant, kann man irgendwo nachlesen, wo diese Notation eingesetzt wird und was sie bedeutet?
              Seit den 1990er Jahren verbreitet sich in Österreich für Wohnungs- und Türnummern auch die umgangssprachliche Bezeichnung Top (von Topos, griechisch für "Ort").
              Wohnungsnummer ? Wikipedia

              Kommentar


              • #8
                Hi,

                Straße und Hausnummer in Deutschland sind ja "normalerweise" durch ein Leerzeichen getrennt.

                Mittels strrpos($adresse, ' ') kann man doch das letzte Leerzeichen ermitteln, um dann mit
                PHP-Code:
                $adresse['Straße'] = substr($adressen,0,$pos); //Bis $pos 
                - die Straße und mit
                PHP-Code:
                $adresse['HsNr'] = substr($adressen,$pos); //Ab $pos 
                - die Hausnummer zu ermitteln.

                Noch eine Kuriosität: In Bayern ("eigenäugig" vor Jahren gesehen) gibt's noch Hausnummern mit Bruchzahlen, siehe Anhang.

                Na denn, auf zum fröhlichen reg_expr-entwickeln

                Gruß
                Günni
                Angehängte Dateien

                Kommentar


                • #9
                  Zitat von Guenni61 Beitrag anzeigen
                  Straße und Hausnummer in Deutschland sind ja "normalerweise" durch ein Leerzeichen getrennt.
                  Nur, wenn die Daten "ordentlich" erfasst wurden. Wer definiert, was "normal" ist? Bei "Google-Recherchen" zu dem Thema bin ich auf ein Supportforum irgendeiner E-Commerce-Software gestoßen. Da wünschten sich die Anwender getrennte Eingabefelder für Straße und Adresse. Sie waren mit Kunden konfrontiert, die entweder die Hausnummer ganz weggelassen oder ein trennendes Leerzeichen vergessen hatten. Deswegen habe ich in meiner oben geposteten Lösung den letzteren Fall berücksichtigt.

                  Man könnte natürlich auch direkt bei der Eingabe durch den Benutzer auf das Vorhandensein einer Nummer prüfen und im Fehlerfall die Korrektur anbieten und darauf hinweisen, dass man ansonsten automatisch die 1 als Hausnummer in die Datenbank aufnimmt. Das erscheint mir sinnvoller, als nachträglich versuchen, zu erraten, was denn gemeint sein könnte.

                  Mittels strrpos($adresse, ' ') kann man doch das letzte Leerzeichen ermitteln, um dann mit
                  PHP-Code:
                  $adresse['Straße'] = substr($adressen,0,$pos); //Bis $pos 
                  - die Straße und mit
                  PHP-Code:
                  $adresse['HsNr'] = substr($adressen,$pos); //Ab $pos 
                  - die Hausnummer zu ermitteln.
                  Das Gleiche tut ein einfach(st)er Regex: '/\S+\z/'. Und er scheitert genauso wie deine aufwendigere Logik, wenn nach der Hausnummer noch etwas kommt, wie bspw. "Bahnhofstraße 7 a".

                  Noch eine Kuriosität: In Bayern ("eigenäugig" vor Jahren gesehen) gibt's noch Hausnummern mit Bruchzahlen, siehe Anhang.
                  Schönes Foto. Wikipedia suggeriert, dass solche Nummern in den letzten Jahren "wegrationalisiert" wurden. Trotzdem hab ich sie vorsichtshalber in meinen obigen Regex aufgenommen. '/\pN/u' findet mehr als nur die ASCII-Ziffern von 0 bis 9. Sieht man ja auch an meinem Beispiel "Große Heimstraße 2½" ...

                  Das ändert aber alles nichts, wenn der Threaderöffner auch Adressen außerhalb des deutschen Sprachraums verarbeiten will. Dann wird die Sache komplizierter.

                  Na denn, auf zum fröhlichen reg_expr-entwickeln
                  Ich denke, ein RegEx wird da nicht reichen. Man benötigt einen richtigen Parser, der auch die anderen Adress-Felder berücksichtigt, um Länder-spezifische Notationen richtig zuordnen zu können. Wenn man das wirklich vollautomatisch machen möchte. Wenn man überhaupt die Hausnummer abtrennen will. Mir ist immer noch nicht klar, warum man das tun sollte ...
                  Klingon function calls do not have “parameters”‒they have “arguments”‒and they always win them!

                  Kommentar


                  • #10
                    Zitat von fireweasel Beitrag anzeigen
                    Man könnte natürlich auch direkt bei der Eingabe durch den Benutzer auf das Vorhandensein einer Nummer prüfen und im Fehlerfall die Korrektur anbieten und darauf hinweisen, dass man ansonsten automatisch die 1 als Hausnummer in die Datenbank aufnimmt.
                    Wäre es da nicht einfacher ein separates Eingabefeld für die Hausnummer anzubieten?

                    Kommentar


                    • #11
                      Zitat von h3ll Beitrag anzeigen
                      Wäre es da nicht einfacher ein separates Eingabefeld für die Hausnummer anzubieten?
                      [scherz]In HTML6 wird es dafür spezielle Eingabefelder geben, input-Controls mit dem Attribut "housenumber" und entsprechender Validierung. [/scherz]

                      Prinzipiell ja. Nur hast du dann wieder das Problem, dass du die Adresse anschließend richtig zusammensetzen musst: Wenn die Nummer mal am Ende (AT|CH|DE), am Anfang (UK|US), in der Mitte (BE) oder am Anfang oder am Ende eingefügt werden muss, wird das wieder lustig. Und wenn meine Adresse "Dunkeldorf, Hauptstraße" lautet, was gebe ich dann in das Feld ein?

                      Und dann wäre da noch die Validierung des Hausnummern-Feldes: Ziffern reichen nicht, wie wir bereits gesehen haben. Dazu kämen noch Adresszusätze und User, die nicht wissen, wo sie was reinschreiben sollen, wie in dem oben verlinkten Support-Thread schön beschrieben. Dann nehme ich lieber die komplette Adresse entgegen und hoffe, dass der von mir beauftragte Post-Dienstleister dazu auch die richtige Wohnungstür findet.

                      Hinzu kommt noch die Anwenderfreundlichkeit: Arbeitest du dich lieber durch ein Formular mit unzähligen Einzelfeldern, oder sind dir "Freiform"-Eingaben lieber? Ich kann es nicht ausstehen, bspw. mein Geburtsdatum in drei Einzelteilen eingeben zu müssen. Mein Billig-Smartphone kann mir zwar auf Zuruf den Weg zum Bäcker zeigen, aber wenn ich irgendwo meine Postadresse hinterlassen soll, muss ich die Hausnummer in ein separates Feld eintragen?
                      Zuletzt geändert von fireweasel; 14.09.2013, 13:06.
                      Klingon function calls do not have “parameters”‒they have “arguments”‒and they always win them!

                      Kommentar


                      • #12
                        There is a app for that

                        Hallo Gemeinde,

                        wir haben eine API welche Adressen im Internet überprüft, korrigiert und das ergebnis in einzelnen Werten wieder zurückgibt.
                        Als Showcase haben wir ein Excel Add-In damit gebaut. Aber das ganze gibt es auch als API.

                        Excel Showcase Video: https://www.youtube.com/channel/UCc7idkk33JeaU__zt9oosnA/videos
                        Developer Registrierung: https://methis.at/products/api/
                        API-Doku: https://hercules.methis.at/

                        Beste Grüße aus Salzburg

                        Kommentar


                        • #13
                          Weltweite Adressparser (mit zusätzlicher Quasi-Existenz-Abfrage übers OpenStreetMap-API) gibts auch von anderen Anbietern. Bspw.:

                          International Address Parser - Test page

                          Namen einem Geschlecht zuordnen kann man (nicht nur) per PHP schon länger -- kostenlos mit zusätzlicher Funktionalität, ohne nötige Netzwerkverbindung und auf allen gängigen Betriebssystemen (unter Windows genügt eine DLL, keine Setup.exe nötig).
                          Klingon function calls do not have “parameters”‒they have “arguments”‒and they always win them!

                          Kommentar


                          • #14
                            Einfach mal selber testen

                            Hallo fireweasel,

                            die Korrektur vom International Address Parser funktioniert aber gar nicht gut. Selbst geringe Abweichungen vom echten Namen wurden bei unseren Tests nicht erkannt. z.B. Vogelwiederstraße anstatt Vogelweiderstraße.

                            Bei METHIS werden sogar solche Adressen erkannt und korrigiert:
                            [COLOR=black]5020/VOGELWEIDERSTR./44/5[/COLOR]
                            [COLOR=black]127 CalledeAtocha Madrad[/COLOR]
                            [COLOR=black]RUEDERIVOLI184PARIS[/COLOR]
                            [COLOR=black]NørreVoldgade82Kopenhagn[/COLOR]
                            [COLOR=black]FleetStreet152London (VIP)[/COLOR]
                            [COLOR=black]VIA NOMENTANA 1141 Rom[/COLOR]
                            [COLOR=black]Getreidegasse_26_Salzburg[/COLOR]
                            [COLOR=black]Rubens\1\04317?[/COLOR]
                            [COLOR=black]Bahnhofplatz-5-Zürich!!![/COLOR]

                            Hier kann man es auch selbst ausprobieren:

                            Weltweite Addresskorrektur

                            Und bezüglich Geschlechtererkennung - ja gibt es auch kostenlos, aber wir reden hier halt nicht von 40.000 Namen, sondern von über 800.000 Namen aus über 140 Ländern.

                            getGender Extended International am Vornamen Geschlecht erkennen

                            Kommentar


                            • #15
                              Ich wollte lediglich Alternativen aufzeigen. Ob die besser oder schlechter sind, muss der an Adress-Prüfungen interessierte Webentwickler schon selbst herausfinden ...

                              Was mir an eurem Service fehlen würde, ist eine PHP-Anbindung oder wenigstens ein paar PHP-Source-Code-Beispiele zur API-Nutzung. Schließlich sind wir hier in einem PHP-Forum und keinem Excel-User-Board.

                              Zitat von METHIS Beitrag anzeigen
                              ...
                              Und bezüglich Geschlechtererkennung - ja gibt es auch kostenlos, aber wir reden hier halt nicht von 40.000 Namen, sondern von über 800.000 Namen aus über 140 Ländern.

                              getGender Extended International am Vornamen Geschlecht erkennen
                              Wenn die Zahl tatsächlich stimmt, dann solltet ihr mal eure Website updaten. Da steht nämlich:

                              Das METHIS /Excel Add-in verfügt über eine Datenbank mit mehr als 50.000 Einträgen aus Vornamen und Geschlecht ...
                              Understatement ist ja nicht schlecht, aber 50_000 zu 800_000 ist schon ein gewaltiger Unterschied.
                              Klingon function calls do not have “parameters”‒they have “arguments”‒and they always win them!

                              Kommentar

                              Lädt...
                              X