PHP中基于动态键重组重复对象数组值的问题
合并重复orgUnit的对象数组(动态服务器字段)
我有一个包含重复值的对象数组$syncData,其中orgUnitId和orgUnitName字段重复出现,每个对象仅包含一个服务器相关键(如sive、siim、hosp)的非null值。需要将同一orgUnit对应的所有服务器键的非null值合并到单个对象中,这些服务器键是动态的,来源于数组$serversList(字段数量可能变化)。尝试了一段代码但未达到预期效果,具体信息如下:
原始数据 $syncData
$syncData = array( (object)[ "orgUnitId" => "1", "orgUnitName" => "josh", "sive" => "OK", "siim" => null, "hosp"=>null, "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "1", "orgUnitName" => "josh", "sive" => null, "siim" => "ERROR", "hosp" => null, "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "1", "orgUnitName" => "josh", "sive" => null, "siim" => null, "hosp" => "OK", "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "2", "orgUnitName" => "Bill", "sive" => "OK", "siim" => null, "hosp" => null, "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "2", "orgUnitName" => "Bill", "sive" => null, "siim" => "ERROR", "hosp" => null, "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "2", "orgUnitName" => "Bill", "sive" => null, "siim" => null, "hosp" => "ERROR", "date" => "2023-01-19 00:00:00" ], );
期望输出
$syncData = array( (object)[ "orgUnitId" => "1", "orgUnitName" => "josh", "sive" => "OK", "siim" => "ERROR", "hosp" => "OK", "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "2", "orgUnitName" => "Bill", "sive" => "OK", "siim" => "ERROR", "hosp" => "ERROR", "date" => "2023-01-19 00:00:00" ], );
动态服务器键来源 $serversList
$serversList = array( (object)[ "name"=> "sive" ], (object)[ "name"=> "siim" ], (object)[ "name" => "hosp" ] );
尝试的代码
for ($i = 0; $i < (count($syncData)-1); $i++) { foreach ($serversList as $serverkey => $serverValue) { if($syncData[$i]->{$serverValue->name}==null){ $val= $syncData[$i]; $val->{$serverValue->name}= $syncData[$i + 1]->{$serverValue->name}; array_push($data_copy,$val); } } }
错误结果
$syncData = array( (object)[ "orgUnitId" => "1", "orgUnitName" => "josh", "sive" => "OK", "siim" => "ERROR", "hosp"=>null, "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "1", "orgUnitName" => "josh", "sive" => null, "siim" => "ERROR", "hosp" => "ERROR", "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "1", "orgUnitName" => "josh", "sive" => "OK", "siim" => null, "hosp" => "ERROR", "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "2", "orgUnitName" => "Bill", "sive" => "OK", "siim" => null, "hosp" => null, "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "2", "orgUnitName" => "Bill", "sive" => null, "siim" => "ERROR", "hosp" => null, "date" => "2023-01-19 00:00:00" ], (object)[ "orgUnitId" => "2", "orgUnitName" => "Bill", "sive" => null, "siim" => null, "hosp" => "ERROR", "date" => "2023-01-19 00:00:00" ], );
解决方案
核心思路是用orgUnitId作为分组键,遍历原始数组时将每个对象的服务器字段值合并到对应分组的对象中:
- 提取
$serversList中的服务器键名,方便后续遍历 - 初始化空数组存储合并结果,键为
orgUnitId - 遍历
$syncData中的每个对象:- 若当前
orgUnitId未在结果数组中,先复制基础字段并初始化所有服务器字段为null - 遍历所有服务器键,将当前对象中的非
null值覆盖到结果对象中
- 若当前
- 最后将结果数组转为索引数组,得到最终合并结果
代码实现:
// 提取服务器键名列表 $serverKeys = array_column($serversList, 'name'); $mergedData = []; foreach ($syncData as $item) { $orgId = $item->orgUnitId; // 初始化该orgUnit的基础对象 if (!isset($mergedData[$orgId])) { $mergedData[$orgId] = (object)[ 'orgUnitId' => $item->orgUnitId, 'orgUnitName' => $item->orgUnitName, 'date' => $item->date ]; // 初始化所有服务器字段为null foreach ($serverKeys as $key) { $mergedData[$orgId]->{$key} = null; } } // 合并非null的服务器字段值 foreach ($serverKeys as $key) { if ($item->{$key} !== null) { $mergedData[$orgId]->{$key} = $item->{$key}; } } } // 转为索引数组得到最终结果 $syncData = array_values($mergedData);
这段代码会动态适配$serversList中的字段,无论字段数量如何变化,都能正确合并同一orgUnitId下的所有服务器字段值,得到符合预期的结果。
内容的提问来源于stack exchange,提问作者amadeu joaquim
相关产品推荐
相关产品推荐

