PHP中按特定规则合并两个不同大小的关联数组
数组合并需求与解决方案
需求说明
以第一个数组的日期键为基准,与第二个数组的日期键匹配:
- 匹配成功时,保留第二个数组对应日期的详情数据
- 未匹配的日期,填充固定结构
[1 => '']
示例数组
$first = [ '2022-10-23' => '2022-10-23', '2022-10-24' => '2022-10-24', '2022-10-25' => '2022-10-25', '2022-10-26' => '2022-10-26', '2022-10-27' => '2022-10-27', '2022-10-28' => '2022-10-28', '2022-10-29' => '2022-10-29' ]; $second = [ '2022-10-24' => [ 'id' => 11, 'user_id' => 1, 'notitie' => 'Mag al helemaal niet', 'datum' => '2022-10-24', 'user_role' => 'client' ], '2022-10-26' => [ 'id' => 15, 'user_id' => 1, 'notitie' => 26, 'datum' => '2022-10-26', 'user_role' => 'client' ], ];
期望结果
Array ( [2022-10-23] => Array ( [1] => ) [2022-10-24] => Array ( [id] => 11 [user_id] => 1 [notitie] => Mag al helemaal niet [datum] => 2022-10-24 [user_role] => client ) [2022-10-25] => Array ( [1] => ) [2022-10-26] => Array ( [id] => 15 [user_id] => 1 [notitie] => 26 [datum] => 2022-10-26 [user_role] => client ) [2022-10-27] => Array ( [1] => ) [2022-10-28] => Array ( [1] => ) [2022-10-29] => Array ( [1] => ) )
尝试代码
if ($agendaButtonInfo == "timeGridWeek"){ $userNotities = array(); $dagenTussen = array(); $period = new DatePeriod( new DateTime($agendaDatumBegin), new DateInterval('P1D'), new DateTime($agendaDatumEinde) ); foreach ($period as $key => $value) { $dagenTussen[$value->format('Y-m-d')] = $value->format('Y-m-d'); } $stmt = $pdo->query("SELECT notitie_client.id, notitie_client.user_id, notitie_client.notitie, notitie_client.datum, user.user_role FROM (notitie_client INNER JOIN user ON notitie_client.user_id = user.id) WHERE notitie_client.user_id='$userId' AND notitie_client.datum BETWEEN '$agendaDatumBegin' AND '$agendaDatumEinde' ORDER BY notitie_client.datum ASC;"); if ($stmt->rowCount() > 0) { while ($row = $stmt->fetch()) { $userNotities[$row["datum"]] = array( "id" => $row["id"], "user_id" => $row["user_id"], "notitie" => $row["notitie"], "datum" => $row["datum"], "user_role" => $row["user_role"]); } } echo "<pre>"; print_r($dagenTussen); echo "<pre>"; print_r($userNotities); $notatieDatum[] = array(); foreach ($userNotities as $notatie){ $notatieDatum[] = $notatie["datum"]; } print_r ($notatieDatum); $eindArray = array(); foreach ($dagenTussen as $dag){ echo "<br>"; if (in_array($dag, $notatieDatum)) { echo "Match found"; print_r ($userNotities); } else { echo "Match not found"; } } }
问题分析与优化方案
你的尝试代码存在几个问题:
- 构建
$notatieDatum时初始添加了空数组,会导致in_array检查出现误判 - 匹配成功时仅输出整个
$userNotities,未将对应数据赋值到结果数组 - 使用
in_array遍历查找效率低,直接检查数组键的存在性更高效
优化后的代码
直接遍历基准日期数组的键,通过isset快速判断是否存在匹配数据:
if ($agendaButtonInfo == "timeGridWeek"){ $userNotities = []; $dagenTussen = []; $period = new DatePeriod( new DateTime($agendaDatumBegin), new DateInterval('P1D'), new DateTime($agendaDatumEinde) ); foreach ($period as $value) { $dateStr = $value->format('Y-m-d'); $dagenTussen[$dateStr] = $dateStr; } // 使用预处理语句防止SQL注入 $stmt = $pdo->prepare("SELECT notitie_client.id, notitie_client.user_id, notitie_client.notitie, notitie_client.datum, user.user_role FROM notitie_client INNER JOIN user ON notitie_client.user_id = user.id WHERE notitie_client.user_id = ? AND notitie_client.datum BETWEEN ? AND ? ORDER BY notitie_client.datum ASC;"); $stmt->execute([$userId, $agendaDatumBegin, $agendaDatumEinde]); while ($row = $stmt->fetch()) { $userNotities[$row["datum"]] = [ "id" => $row["id"], "user_id" => $row["user_id"], "notitie" => $row["notitie"], "datum" => $row["datum"], "user_role" => $row["user_role"] ]; } $eindArray = []; // 遍历基准日期的每个键 foreach ($dagenTussen as $dateKey => $_) { // 检查是否有匹配的记录 if (isset($userNotities[$dateKey])) { $eindArray[$dateKey] = $userNotities[$dateKey]; } else { // 未匹配则填充指定结构 $eindArray[$dateKey] = [1 => '']; } } // 输出结果 echo "<pre>"; print_r($eindArray); echo "</pre>"; }
额外提示
- 原SQL语句存在注入风险,必须使用预处理语句
isset($userNotities[$dateKey])的时间复杂度为O(1),比in_array的O(n)效率高很多
内容的提问来源于stack exchange,提问作者NoobyPhper
相关产品推荐
相关产品推荐

