【问题标题】:Optimizing algorithm to avoid exaggerated script execution time优化算法以避免夸大脚本执行时间
【发布时间】:2015-11-03 20:11:36
【问题描述】:

昨天我在这里问Append array values to another array by keys comparison,我尝试了一些没有成功的事情。我有两个数组$result$result1count($result)204640count($result1)129849 所以它们很大。数组是 PDO 语句执行的结果,如下面的代码所示。这是$result 数组的示例:

'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',
      )

这是$result1 数组的示例:

'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',
      ),

如您所见,$result[1]$result1[1] 共享相同的密钥,对吧?好的,那么我需要将$result1[1] 的内容推送到$result[1] 的末尾并得到类似:

'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',
      )

意思是当两个数组中的键相等时,然后将第二个数组中的值合并或附加到第一个数组中。现在我最好的方法是:

// 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);

但是由于数组的长度,它需要一个永恒的时间,所以有什么建议可以加快这个速度吗?

更新:几乎是一个解决方案

基于 @decese 解决方案我已经重写了一点,所以我先道歉并看看这个。现在我将数组称为$oneArr$twoArr,并且我还写了一个小的输出示例(不要杀了我):

// 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',
      )

这是我想要实现的输出,这意味着当两个数组中的键相等时,然后将第二个数组中的值合并或附加到第一个:

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

我已经完成了这项工作,再次基于第一个答案,我非常感谢您向我解释了一些事情,代码如下:

// 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);

但结果与我想要的不一样,因为我得到了这个:

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

如何避免结果数组上的额外数组?

PS:现在看起来不错:通话时间是 00:01:34

【问题讨论】:

  • 分而治之我的朋友。现在你有 O(n^2)。也许你可以在 SQL 中做一些优化
  • 如果已经有明显的关系,加入查询可能更有意义。
  • @Robert 这是我在 SQL 方面能做的最好的事情,我尝试使用 JOIN 和 UNION 运行并在一个查询中获取所有内容,但最糟糕的是,仅执行查询需要 5 分钟左右
  • 所以也许在你想加入的列上使用索引
  • @Robert 也已经尝试过了,这需要很多时间并且不是最佳方式。我更喜欢依赖 PHP 端并尝试在那里解决而不是 JOIN 查询并一次获得所有结果

标签: php arrays algorithm optimization


【解决方案1】:

你可以使用array_merge_recursive

查看我的工作示例:http://3v4l.org/hQERW
注意:在提供的数据中,只有00180000015oGeXAAU 是两个数组共有的,所以它只合并该键的值

基本上,只需调用

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

PHP.net 说:

array_merge_recursive() 将一个或多个数组的元素合并在一起,以便将一个数组的值附加到前一个数组的末尾。它返回结果数组。

如果输入数组有相同的字符串键,那么这些键的值被合并到一个数组中,这是递归完成的,所以如果一个的值是一个数组本身,该函数也会将它与另一个数组中的相应条目合并。但是,如果数组具有相同的数字键,则后面的值不会覆盖原始值,而是会被追加。

【讨论】:

    【解决方案2】:

    看起来你的数组实际上是由 id 索引的,所以这样做:

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

    当然,如果可能的话,使用JOIN 在数据库中完成所有这些工作是最有意义的。

    【讨论】:

    • 无法加入查询(检查我以前的 cmets),而且我根本没有关注你的示例代码,你能解释一下你想在那里实现什么吗?
    • 对于$result1中的每一项,查看$result中是否存在key(主id),如果存在,将$result1中的值追加到匹配的key $result.
    • array_push 不是你想要的!你想+ 两个数组,或者array_merge 他们。
    • Thx $oneArr[$keyOneArr] += $twoArr[$keyOneArr] 按照您的建议完成了这项工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    相关资源
    最近更新 更多