ReynierPM
ReynierPM

Reputation: 18660

Optimizing algorithm to avoid exaggerated script execution time

Yesterday I ask here Append array values to another array by keys comparison and I have tried a few things without success. I have two arrays $result and $result1. count($result) is 204640 and count($result1) is 129849 so they are huge. The arrays is the result of a PDO statement execution as shown in code below. This is an example for $result array:

'00180000015oGSWAA2' =>
    array (
        'accountId' => '00180000015oGSWAA2',
        'npi' => '1053576223',
        'firstname' => 'Jack',
        'lastname' => 'Cheng',
        'title' => '',
        'accountLastModifiedDate' => '2014-09-09 17:37:15',
        'suffix' => '',
        'fax' => '',
        'address1' => '853 N CHURCH ST',
        'city' => 'SPARTANBURG',
        'stateLicensedId' => '31191',
        'state' => 'SC',
        'phone' => '',
        'zip' => '29303',
        'address2' => '',
        'addressLastModifiedDate' => '2014-09-04 08:44:17',
      ),
'00180000015oGeXAAU' =>
    array (
        'accountId' => '00180000015oGeXAAU',
        'npi' => '1629067301',
        'firstname' => 'Fred',
        'lastname' => 'Thaler',
        'title' => '',
        'accountLastModifiedDate' => '2014-09-09 17:36:41',
        'suffix' => '',
        'fax' => '',
        'address1' => '1 PEARL ST',
        'city' => 'BROCKTON',
        'stateLicensedId' => '58249',
        'state' => 'MA',
        'phone' => '',
        'zip' => '2301',
        'address2' => '',
        'addressLastModifiedDate' => '2014-09-04 04:25:44',
      )

And this is an example for $result1 array:

'001S000000nBvryIAC' =>
    array (
        'tid' => '04T800000008zySEAQ',
        'acsLastModifiedDate' => '2015-01-06 17:19:48',
      ),
'00180000015oGeXAAU' =>
    array (
        'tid' => '04T800000008zzgEAA',
        'acsLastModifiedDate' => '2015-01-07 04:06:40',
      ),
'001S000000nYWcYIAW' =>
    array (
        'tid' => '04T800000008zySEAQ',
        'acsLastModifiedDate' => '2015-02-25 15:45:01',
      ),

As you can see $result[1] and $result1[1] shares the same keys, right? Ok, then what I need is to push the content of $result1[1] on the end of $result[1] and getting something like:

'00180000015oGeXAAU' =>
    array (
        'accountId' => '00180000015oGeXAAU',
        'npi' => '1629067301',
        'firstname' => 'Fred',
        'lastname' => 'Thaler',
        'title' => '',
        'accountLastModifiedDate' => '2014-09-09 17:36:41',
        'suffix' => '',
        'fax' => '',
        'address1' => '1 PEARL ST',
        'city' => 'BROCKTON',
        'stateLicensedId' => '58249',
        'state' => 'MA',
        'phone' => '',
        'zip' => '2301',
        'address2' => '',
        'addressLastModifiedDate' => '2014-09-04 04:25:44',
        'tid' => '04T800000008zzgEAA',
        'acsLastModifiedDate' => '2015-01-07 04:06:40',
      )

Meaning when keys are equal in both arrays then merge or append values from the second one into the first one. Right now my best approach is the following:

// PDO statement
$result = $stmt->fetchAll();

// PDO statement
$result1 = $stmt->fetchAll();

foreach ($result as $key => $row) {
    foreach ($result1 as $key1 => $row1) {
        if ($key === $key1) {
            array_push($row, array_shift($row1));
        }
    }
}

var_dump($row);

But it takes an eternity due to arrays length, so any advice in how to speedup this?

UPDATE: almost a solution

Based on @decese solution I have rewrite this a bit so my apologies in first and take a look to this. Now I called arrays as $oneArr and $twoArr and also I write a small output examples (don't kill me just yet):

// var_export($oneArr)
'00180000015oGSWAA2' =>
    array (
        'target_id' => '00180000015oGSWAA2',
        'firstname' => 'Jack',
      ),
'00180000015oGeXAAU' =>
    array (
        'target_id' => '00180000015oGeXAAU',
        'firstname' => 'Fred',
      )

// var_export($twoArr)
'001S000000nBvryIAC' =>
    array (
        'tid' => '04T800000008zySEAQ',
        'acsLastModifiedDate' => '2015-01-06 17:19:48',
      ),
'00180000015oGeXAAU' =>
    array (
        'tid' => '04T800000008zzgEAA',
        'acsLastModifiedDate' => '2015-01-07 04:06:40',
      )

This is the ouput I want to achieve, meaning when keys are equal in both arrays then merge or append values from the second one into the first one:

'00180000015oGeXAAU' =>
    array (
        'target_id' => '00180000015oGeXAAU',
        'firstname' => 'Fred',
        'tid' => '04T800000008zzgEAA',
        'acsLastModifiedDate' => '2015-01-07 04:06:40',
      )

I have this done, again based on first answer which I thanks a lot for clear a bit things to me, with the following code:

// Fetch results from first SQL query
$result = $stmt->fetchAll();

// Fetch only two keys from the entire and put them on $oneArr
foreach ($result as $row) {
    $oneArr[$row['target_id']] = [
        'target_id' => $row['target_id'],
        'firstname' => $row['firstname']
    ];
}

// Fetch results from second SQL query
// yes, var names are the same not matter, I will only use one time
$result = $stmt->fetchAll();

// Fetch only two keys from the entire and put them on $twoArr
foreach ($result as $row) {
    $twoArr[$row['target_id']] = [
        'tid'    => $row['tid'],
        'acslmd' => $row['acslmd']
    ];
}

$i = 0;
foreach ($oneArr as $keyOneArr => $valueOneArr) {
    if (array_key_exists($keyOneArr, $twoArr)) {
        array_push($oneArr[$keyOneArr], $twoArr[$keyOneArr]);
        $i++;
    }
}

var_export($oneArr);

But result is not the same as I want since I got this:

'00180000015oGeXAAU' =>
    array (
        'target_id' => '00180000015oGeXAAU',
        'firstname' => 'Fred',
        0 =>
            array (
                'tid' => '04T800000008zzgEAA',
                'acslmd' => '2015-01-07 04:06:40',
        ),
    ),

How I can avoid the extra array on the result array?

PS: Times looks good now: Call time was 00:01:34

Upvotes: 0

Views: 51

Answers (2)

Alex Tartan
Alex Tartan

Reputation: 6826

You could use array_merge_recursive

See my working example: http://3v4l.org/hQERW
Note: in the provided data, only 00180000015oGeXAAU is common to both arrays, so it only merges the values for that key

Basically, just call

$result = array_merge_recursive($result, $result1);

PHP.net says:

array_merge_recursive() merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.

If the input arrays have the same string keys, then the values for these keys are merged together into an array, and this is done recursively, so that if one of the values is an array itself, the function will merge it with a corresponding entry in another array too. If, however, the arrays have the same numeric key, the later value will not overwrite the original value, but will be appended.

Upvotes: 2

deceze
deceze

Reputation: 522016

Looks like your arrays are actually indexed by the ids, so do this:

foreach ($result1 as $key => $value) {
    if (isset($result[$key])) {
        $result[$key] += $value;
    }
}

Of course, doing all this work in the database using a JOIN would make the most sense to begin with, if possible.

Upvotes: 2

Related Questions