-
-
Save christiaanwesterbeek/c574beaf73adcfd74997 to your computer and use it in GitHub Desktop.
let re = /^(\d*[\wäöüß\d '\/\\\-\.]+)[,\s]+(\d+)\s*([\wäöüß\d\-\/]*)$/i | |
let adressen = [ | |
'Dorpstraat 2', | |
'Dorpstr. 2', | |
'Laan 1933 2', | |
'18 Septemberplein 12', | |
'Kerkstraat 42-f3', | |
'Kerk straat 2b', | |
'42nd street, 1337a', | |
'1e Constantijn Huigensstraat 9b', | |
'Maas-Waalweg 15', | |
'De Dompelaar 1 B', | |
'Kümmersbrucker Straße 2', | |
'Friedrichstädter Straße 42-46', | |
'Höhenstraße 5A', | |
'Saturnusstraat 60-75', | |
'Saturnusstraat 60 - 75', | |
'Plein \'40-\'45 10', | |
'Plein 1945 1', | |
'Steenkade t/o 56', | |
'Steenkade a/b Twee Gezusters', | |
'1, rue de l\'eglise' | |
] | |
let matches = adressen.map((adres) => { | |
let match = adres.match(re) | |
return `<td>${adres}</td><td>${match && match.shift() && match.join('</td><td>')}</td>` | |
}) | |
document.write(`<table><tr>${matches.join('</tr><tr>')}</tr></table>`) | |
// jsFiddle version here: https://jsfiddle.net/devotis/3wLv7ex2 | |
// Changes 2017-08-23 | |
// allow / and \ in street names | |
// use es6 and drop the semicolons | |
// refactor code to produce html table |
Het wordt tijd voor een echte Github repo met tests!
Hi @christiaanwesterbeek voor PHP testing heb ik vast een begin gemaakt zie: https://github.com/WebRTB/address-splitter
Is wel nog steeds W.I.P. :-) pull requests zijn meer dan welkom, als het een beetje draait zal ik hem publiceren op composer voor iedereen.
Waarom niet eens een Lexer proberen wellicht in plaats van in een regex te krijgen?
Ik weet hij is nog niet perfect, maar veel al werkt "redelijk". (en nee dit is een half uur lexer werk ;-))
Maakt gebruik van de doctrine/lexer
package :-).
<?php
namespace App\Lexer;
use Doctrine\Common\Lexer\AbstractLexer;
class CharacterTypeLexer extends AbstractLexer
{
const T_LETTER = 1;
CONST T_NUMBER = 2;
CONST T_SPACE = 3;
CONST T_DELMITER = 4;
CONST T_UNKNOWN = 99;
protected function getCatchablePatterns()
{
return [];
}
protected function getNonCatchablePatterns()
{
return [];
}
protected function getType(&$value)
{
if (preg_match('/\p{L}+/', $value)) {
return self::T_LETTER;
}
elseif (preg_match('/[0-9]/', $value)) {
return self::T_NUMBER;
}
elseif (preg_match('/[:\-,]/', $value)) {
return self::T_DELMITER;
}
elseif ($value === ' ') {
return self::T_SPACE;
}
else {
return self::T_UNKNOWN;
}
}
}
<?php
namespace App\Lexer;
use App\Lexer\CharacterTypeLexer;
class TestEvaluater
{
private $lexer;
private $splittedData = [
'street' => null,
'number' => null,
'addition' => null
];
public function __construct(CharacterTypeLexer $lexer)
{
$this->lexer = $lexer;
}
public function getSplittedAddress($string)
{
$this->lexer->setInput($string);
$this->lexer->moveNext();
$this->lookingFor = 'street';
while (true) {
if (!$this->lexer->lookahead) {
break;
}
$this->lexer->moveNext();
if ($this->lexer->token['type'] == CharacterTypeLexer::T_SPACE) {
if (! is_null($lookahead = $this->lexer->lookahead)) {
if ($lookahead['type'] !== CharacterTypeLexer::T_LETTER) {
if ($this->lookingFor == 'street') {
// Check if this number is not part of the streetname
$stillStreet = false;
while (true) {
if (is_null($peek = $this->lexer->peek())) {
break;
}
if ($peek['type'] == CharacterTypeLexer::T_DELMITER) {
break;
}
if ($peek['type'] == CharacterTypeLexer::T_SPACE) {
if (! is_null($numberPeek = $this->lexer->peek())) {
if ($numberPeek['type'] == CharacterTypeLexer::T_NUMBER) {
$stillStreet = true;
}
}
}
}
}
if (! $stillStreet) {
$this->moveToNextLooking();
} else {
$this->splittedData[$this->lookingFor][] = $this->lexer->token['value'];
$stillStreet = false;
}
} else {
if ($this->lookingFor == 'number') {
$this->moveToNextLooking();
} else {
$this->splittedData[$this->lookingFor][] = $this->lexer->token['value'];
}
}
}
} else {
$this->splittedData[$this->lookingFor][] = $this->lexer->token['value'];
if (! is_null($lookahead = $this->lexer->lookahead)) {
if ($lookahead['type'] == CharacterTypeLexer::T_LETTER && $this->lookingFor == 'number') {
$this->moveToNextLooking();
}
}
}
}
return $this->splittedData;
}
protected function moveToNextLooking() : void
{
if ($this->lookingFor == 'street') {
$this->lookingFor = 'number';
} elseif ($this->lookingFor == 'number') {
$this->lookingFor = 'addition';
}
}
}
Gebruik:
use App\Lexer\TestEvaluater;
use App\Lexer\CharacterTypeLexer;
$test = new TestEvaluater(new CharacterTypeLexer());
$test->getSplittedAddress('adres');
@Noxxie
Omdat dat PHP is? Daarmee bedoel ik: deze regex kan je in de meeste talen gewoon parsen. Zou mooi zijn als dit idd een repo wordt, maar dan puur voor de regex, met testen. die wellicht zelfs meerdere talen ondersteund? Ik wil wel helpen als @christiaanwesterbeek dat nog gaat oppakken :-)
@Remco75 het is wellicht nog niet perfect maar https://github.com/NoxxieNl/Nladdresslexer
We figured out a few problems with german addresses, where the house number is a range or even written like 5+6.
Here is an updated Regex.
RE: ^(\d*[\p{L}\d '\/\\\-\.]+?)[,\s]+((?:\d+)\s*(?:[\p{L}\d\/]*(?:\s*[-+]\s*[\p{L}\d\-+\/]*)?))$
RE with sample data: https://regex101.com/r/BaQUN4/1
Bye
We figured out a few problems with german addresses, where the house number is a range or even written like 5+6. Here is an updated Regex. RE:
^(\d*[\p{L}\d '\/\\\-\.]+?)[,\s]+((?:\d+)\s*(?:[\p{L}\d\/]*(?:\s*[-+]\s*[\p{L}\d\-+\/]*)?))$
RE with sample data: https://regex101.com/r/BaQUN4/1 Bye
Here's the python equivalent if anyone is interested:
r"^(\d*[\w\d '\/\\\-\.]+?)[,\s]+((?:\d+)\s*(?:[\w\d\/]*(?:\s*[-+]\s*[\w\d\-+\/]*)?))$"
Beste collega's -g, wanneer het huisnummer + toevoeging bijvoorbeeld 24-2 is, wordt deze niet goed gesplitst in de regex die ik gebruik. De 2 wordt dan als huisnummer gezien. Is hier al een oplossing voor? Groet
Eigenlijk zou de "Nieuwe gracht 224 2" twee keer door de regEx moeten. Als er dan opnieuw een nummer ontstaat was deze nog niet volledig verwerkt. Geen idee hoe je dat in een RegEx moet doen. De regex gaat wel goed als de 2 (vermoedelijk de verdieping) aangegeven wordt als -2 of /2 of 2hoog.
Dit lost natuurlijk niet het probleem van "Plein 1944 2" op. Tussen deze en "Nieuwe gracht 224 2" is geen verschil te zien.