I developed a PHP function to get a not formatted address and split it in a street name and number.
Following are some patterns of received addresses
- StreetName Number
- SrtreetName, Number
- Number StreetName
- Number-Number StreetName
- StreetName, Number, Complement
- StreetName Number/Number
- StreetName Number - ZipCode (ZipCode could be ignored)
- StreetName (without number)
I'm using regex to identify the pattern and then splitting it. Here is the function (the code is commented for better understanding):
<?php
function getInfoAddress ($address)
{
$return = array('street'=>NULL,
'number'=>NULL,
'complement'=>NULL);
//firstly, erase spaces of the strings
$addressWithoutSpace = str_replace(' ', '', $address);
//discover the pattern using regex
if(preg_match('/^([0-9.-])+(.)*$/',$addressWithoutSpace) === 1) {
//here, the numbers comes first and then the information about the street
$info1 = preg_split('/[[:alpha:]]/', $addressWithoutSpace);
$info2 = preg_split('/[0-9.-]/', $address);
$return['number'] = $info1[0];
$return['street'] = end($info2);
}
elseif(preg_match('/^([[:alpha:]]|[[:punct:]])+(.)*$/',$addressWithoutSpace) === 1) {
//here, I have a alpha-numeric word in the first part of the address
if(preg_match('/^(.)+([[:punct:]])+(.)*([0-9.-])*$/',$addressWithoutSpace) === 1) {
if(preg_match('/,/',$addressWithoutSpace) === 1) {
//have one or more comma and ending with the number
$info1 = explode(",", $address);
$return['number'] = trim(preg_replace('/([^0-9-.])/', ' ', end($info1)));//the last element of the array is the number
array_pop($info1);//pop the number from array
$return['street'] = str_replace(",", "",implode(" ",$info1));//the rest of the string is the street name
}
else {
//finish with the numer, without comma
$info1 = explode(" ", $address);
$return['number'] = end($info1);//the last elemento of array is the number
array_pop($info1);//pop the number from array
$return['street'] = implode(" ",$info1);//the rest of the string is the street name
}
}
elseif(preg_match('/^(.)+([0-9.-])+$/',$addressWithoutSpace) === 1) {
//finish with the number, without punctuation
$info1 = explode(" ", $address);
$return['number'] = end($info1);//the last elemento of array is the number
array_pop($info1);//pop the number from array
$return['street'] = implode(" ",$info1);//the rest of the string is the street name
}
else {
//case without any number
if (preg_match('/,/',$addressWithoutSpace) === 1) {
$return['number'] = NULL;
$endArray = explode(',', $address);
$return['complement'] = end($endArray);//complement is the last element of array
array_pop($endArray);// pop the last element
$return['street'] = implode(" ", $endArray);//the rest of the string is the name od street
}
else {
$return['number'] = NULL;
$return['street'] = $address;//address is just the street name
}
}
}
return ($return);
}
$address = $_POST['address'];
$addressArray = getInfoAddress($address);
print_r($addressArray);
?>
This is working in the most cases (enough for me for while), so I'd like to improve some points:
- Improve Readability: I care with readable code, but in this case I think that I couldn't be a good job. Are there some useless if/else block for example?
- Improve Reliability: The code fails in some cases (when the street name includes number like in "5thAvenue" or when the complement is before number like "rue de la montagne BL2 52", for exemple). Are there some way to improve the reliability?
- I also would like some suggestions of improvement without the use of regex, although I have not been able to figured out anything in this way.
$return
for each input. \$\endgroup\$