Tried this on twelve different strings that were similar to yours and it worked just fine:
function str_to_address($context) {
$context_parts = array_reverse(explode(" ", $context));
$zipKey = "";
foreach($context_parts as $key=>$str) {
if(strlen($str)===5 && is_numeric($str)) {
$zipKey = $key;
break;
}
}
$context_parts_cleaned = array_slice($context_parts, $zipKey);
$context_parts_normalized = array_reverse($context_parts_cleaned);
$houseNumberKey = "";
foreach($context_parts_normalized as $key=>$str) {
if(strlen($str)>1 && strlen($str)<6 && is_numeric($str)) {
$houseNumberKey = $key;
break;
}
}
$address_parts = array_slice($context_parts_normalized, $houseNumberKey);
$string = implode(' ', $address_parts);
return $string;
}
This assumes a house number of at least two digits, and no greater than six. This also assumes that the zip code isn't in the "expanded" form (e.g. 12345-6789). However this can be easily modified to fit that format (regex would be a good option here, something like (d{5}-d{4})
.
But using regex for parsing user-inputted data... Not a good idea here, because we just don't know what a user is going to input because there were (as one can assume) no validations.
Walking through the code and logic, starting with creating the array from the context and grabbing the zip:
// split the context (for example, a sentence) into an array,
// so we can loop through it.
// we reverse the array, as we're going to grab the zip first.
// why? we KNOW the zip is 5 characters long*.
$context_parts = array_reverse(explode(" ", $context));
// we're going to store the array index of the zip code for later use
$zipKey = "";
// foreach iterates over an object given the params,
// in this case it's like doing...
// for each value of $context_parts ($str), and each index ($key)
foreach($context_parts as $key=>$str) {
// if $str is 5 chars long, and numeric...
// an incredibly lazy check for a zip code...
if(strlen($str)===5 && is_numeric($str)) {
$zipKey = $key;
// we have what we want, so we can leave the loop with break
break;
}
}
Do some tidying so we have a better object to garb the house number from
// remove junk from $context_array, since we don't
// need stuff after the zip
$context_parts_cleaned = array_slice($context_parts, $zipKey);
// since the house number comes first, let's go back to the start
$context_parts_normalized = array_reverse($context_parts_cleaned);
And then let's grab the house number, using the same basic logic that we did the zip code:
$houseNumberKey = "";
foreach($context_parts_normalized as $key=>$str) {
if(strlen($str)>1 && strlen($str)<6 && is_numeric($str)) {
$houseNumberKey = $key;
break;
}
}
// we probably have the parts we for the address.
// let's do some more cleaning
$address_parts = array_slice($context_parts_normalized, $houseNumberKey);
// and build the string again, from the address
$string = implode(' ', $address_parts);
// and return the string
return $string;