Home > Mobile >  php indexed array manipulation and filtering
php indexed array manipulation and filtering

Time:08-24

I have an array manipulation/situation that I cannot figure out. In a nutshell:

Get a string such as:

$testString = 'John doe 123 Main st 77555';

I am trying to get things split up to be 3 main parts such as:

$fname = 'John';
$lname = 'doe';
$address = '123 Main st 77555';

Currently I am exploding the array as such:

$splitTestString = explode(" ", $testString");

which gives me the string inside an array.

I've tried a for loop to go through the exploded string:

for($i = 0; $i <= count($splitTestString); $i  ) {
  $fname = $splitTestString[0];
  $lname = $splitTestString[1];
  if(is_numeric($splitTestString[2])) { //take into account 2 last names
    $newAddress = $splitTestString[2];
  } else {
    $lname .= ' '.$splitTestString[2];
  }
}

But I am not sure how to get the address after the initial numbers all into its own variable. Another string example:

$testString = 'John doe smith 123 main st 77555';
$fname = 'John';
$lname = 'doe smith';
$newAddress = '123 main st 77555';

The user would be instructed to enter the information in the above format of first name, last name, address and zip code.

This is my first question out of all the searches I've done on here and please let me know if I've not followed the rules properly. I'm just at my wits end on this problem and cannot seem to find a solution to this situation. Thanks in advance!

CodePudding user response:

You don't need to do everything in a single loop, you should come up with a process for populating the name variables until you hit a word that starts with a number (is this really a safe assumption though?), then simply join the remainder into the address.

If possible, you should go back to the drawing board and provide a way for the user to provide the information in separate fields.

$testString = 'John doe smith villalobos garcia navarro 123 Main st 77555';
$parts = explode(' ', $testString);

// Don't assume we will always have a first or last name, there could be only an address
$fname = '';

// Set up a buffer for the last name words
$lnameBuffer = [];

// Process input buffer until we hit a part that begins with a number
while(!is_numeric(substr($parts[0], 0, 1)))
{
    // Shift the next word off of the buffer
    $currPart = array_shift($parts);
    
    /*
     * If we don't have a first name yet, set it
     * Otherwise, append the word to the last name buffer
     */
    if(empty($fname))
    {
        $fname = $currPart;
    }
    else
    {
        $lnameBuffer[] = $currPart;
    }
}

// Join the last name buffer to populate the $lname variable
$lname = implode(' ', $lnameBuffer);

// The rest of the input buffer contains the address
$newAddress = implode(' ', $parts);

echo 'fname: '.$fname.PHP_EOL;
echo 'lname: '.$lname.PHP_EOL;
echo 'newAddress: '.$newAddress.PHP_EOL;

You could however achieve this much more easily using regex.

$testString = 'John doe smith villalobos garcia navarro 123 Main st 77555';

preg_match('/([^\s]\S )\s([^\d]*)(.*)/', $testString, $matches);

$fname      = $matches[1];
$lname      = $matches[2];
$newAddress = $matches[3];

echo 'fname: '.$fname.PHP_EOL;
echo 'lname: '.$lname.PHP_EOL;
echo 'newAddress: '.$newAddress.PHP_EOL;

CodePudding user response:

If your string is always formatted like "firstname lastname everything else is the address" you can just pass explode a limit like so:

$str = 'John doe 123 Main st 77555';
$parts = explode(' ', $str, 3);
var_dump($parts);

//array(3) {
//  [0]=>
//  string(4) "John"
//  [1]=>
//  string(3) "doe"
//  [2]=>
//  string(17) "123 Main st 77555"
//}

If you need to split with a rule like 'the first time we see a number indicates the start of an address' you can just find that and split the string up like so:

$str = 'john doe smith 123 fake street paris france';
$matches = [];
preg_match('/[0-9]/', $str, $matches, PREG_OFFSET_CAPTURE);
$numberPosition = $matches[0][1]; // this is the first matching element, and its position

$left = trim(substr($str, 0, $numberPosition)); // left side of the found number
$right = trim(substr($str, $numberPosition));   // right side of the found number

var_dump([
  $left, $right
]);

//array(2) {
//  [0]=>
//  string(20) "john doe smith"
//  [1]=>
//  string(26) "123 fake street paris france"
//}

  • Related