
本教程旨在解决如何根据一个关联数组的值(例如,视图计数)来重构另一个包含对象(例如,文章列表)的数组。我们将学习一种高效的方法,通过构建id到对象的映射,然后利用视图数组的顺序和值作为新数组的键,从而实现数据的重新组织和排序,确保最终输出符合特定业务逻辑。
引言与问题定义
在PHP开发中,我们经常会遇到需要整合来自不同数据源的信息,并按照特定规则进行重组的情况。一个常见场景是,您可能有一个数组存储了某个实体的ID及其对应的统计数据(例如,文章的ID和它的浏览量),同时有另一个数组包含了这些实体的完整对象数据(例如,WP_Post对象列表)。我们的目标是将这些对象根据其浏览量进行重新索引,并按照浏览量的大小(或由浏览量数组定义的顺序)进行排序。
例如,我们有以下两个数组:
-
$views 数组: 这是一个关联数组,键是实体ID,值是对应的统计数据(如浏览量)。这个数组的顺序通常已经预先排好,代表了我们期望的最终排序。
$views = [ 1851 => 12, // ID 1851 浏览量 12 14341 => 7, // ID 14341 浏览量 7 17834 => 3 // ID 17834 浏览量 3 ];登录后复制 -
$most_seen_list 数组: 这是一个包含 WP_Post 对象的索引数组,每个对象都包含一个 ID 属性以及其他详细信息。
立即学习“PHP免费学习笔记(深入)”;
$most_seen_list = [ (object) [ 'ID' => 17834, 'post_date' => '2021-10-20 16:01:50', 'post_date_gmt' => '2021-10-20 21:01:50' ], (object) [ 'ID' => 14341, 'post_date' => '2021-06-01 17:57:00', 'post_date_gmt' => '2021-06-01 22:57:00' ], (object) [ 'ID' => 1851, 'post_date' => '2021-02-13 18:09:00', 'post_date_gmt' => '2021-02-13 23:09:00' ] ];登录后复制
我们的期望输出是一个新的数组,其键是 $views 数组中的值(浏览量),而值是对应的 WP_Post 对象,并且整个数组的顺序与 $views 数组的键值顺序保持一致:
Array (
[12] => WP_Post Object ( /* ID 1851 的对象 */ )
[7] => WP_Post Object ( /* ID 14341 的对象 */ )
[3] => WP_Post Object ( /* ID 17834 的对象 */ )
)
解决方案:高效重构策略
要实现上述目标,我们需要一种能够快速查找并按指定顺序构建新数组的方法。直接使用嵌套循环(即在遍历 $views 数组时,每次都遍历 $most_seen_list 数组来查找匹配的ID)虽然可行,但对于大型数据集而言效率低下,时间复杂度为 O(N*M),其中 N 是 $views 的元素数量,M 是 $most_seen_list 的元素数量。
更高效的策略是首先对 $most_seen_list 数组进行预处理,将其转换为一个以 ID 为键的关联数组。这样,后续在遍历 $views 数组时,就可以通过ID直接进行 O(1) 的查找,将整体时间复杂度优化为 O(N+M)。
步骤1:构建对象ID索引映射
首先,我们将 $most_seen_list 数组转换为一个以对象 ID 为键的关联数组。这使得我们能够通过ID快速检索到对应的对象。
$most_seen_list_indexed = [];
foreach ($most_seen_list as $obj) {
// 假设对象具有可访问的 'ID' 属性
$most_seen_list_indexed[$obj->ID] = $obj;
}
现在,$most_seen_list_indexed 看起来会是这样:
Array (
[17834] => WP_Post Object ( /* ID 17834 的对象 */ )
[14341] => WP_Post Object ( /* ID 14341 的对象 */ )
[1851] => WP_Post Object ( /* ID 1851 的对象 */ )
)
步骤2:依据视图数据重构
接下来,我们遍历 $views 数组。对于 $views 数组中的每一个键(即实体ID)和值(即浏览量),我们执行以下操作:
- 使用 $views 数组的键(ID)在 $most_seen_list_indexed 中查找对应的对象。
- 如果找到对象,则将其赋值给新的结果数组,新数组的键为 $views 数组的当前值(浏览量)。
这种方法自然地保持了 $views 数组所定义的顺序,并利用其值作为新数组的键。
完整代码实现
<?php
// 示例数据
$views = [
1851 => 12,
14341 => 7,
17834 => 3
];
// 为了演示方便,将WP_Post Object模拟为stdClass
$most_seen_list = [
(object) [ 'ID' => 17834, 'post_date' => '2021-10-20 16:01:50', 'post_date_gmt' => '2021-10-20 21:01:50' ],
(object) [ 'ID' => 14341, 'post_date' => '2021-06-01 17:57:00', 'post_date_gmt' => '2021-06-01 22:57:00' ],
(object) [ 'ID' => 1851, 'post_date' => '2021-02-13 18:09:00', 'post_date_gmt' => '2021-02-13 23:09:00' ]
];
// 步骤1: 构建对象ID索引映射
$most_seen_list_indexed = [];
foreach ($most_seen_list as $obj) {
$most_seen_list_indexed[$obj->ID] = $obj;
}
// 步骤2: 依据视图数据重构新数组
$newResult = [];
foreach ($views as $id => $view_count) {
// 检查ID是否存在于索引映射中
if (isset($most_seen_list_indexed[$id])) {
// 使用视图计数作为新数组的键,并将对应的对象赋值
$newResult[$view_count] = $most_seen_list_indexed[$id];
}
}
// 打印结果
echo "<pre>";
print_r($newResult);
echo "</pre>";
?>
结果展示
运行上述代码,您将得到以下输出:
Array
(
[12] => stdClass Object
(
[ID] => 1851
[post_date] => 2021-02-13 18:09:00
[post_date_gmt] => 2021-02-13 23:09:00
)
[7] => stdClass Object
(
[ID] => 14341
[post_date] => 2021-06-01 17:57:00
[post_date_gmt] => 2021-06-01 22:57:00
)
[3] => stdClass Object
(
[ID] => 17834
[post_date] => 2021-10-20 16:01:50
[post_date_gmt] => 2021-10-20 21:01:50
)
)
这个结果完全符合我们预期的格式和顺序。
性能考量与最佳实践
- 效率提升: 通过先构建ID索引映射,我们将查找操作从 O(M) 降低到 O(1),从而将整体算法复杂度从 O(N*M) 优化为 O(N+M)。这对于处理包含大量数据(例如数千或数万个对象)的数组时,性能提升尤为显著。
- 数据一致性: 在实际应用中,务必确保 $views 数组中的ID在 $most_seen_list 中都有对应的对象。如果 $views 中包含 $most_seen_list 中不存在的ID,isset($most_seen_list_indexed[$id]) 检查可以有效避免错误或空值被添加到结果数组中。
- 灵活性: 这种模式不仅限于文章浏览量,可以应用于任何需要根据一个关联数组的键值对来重排和重索引另一个对象数组的场景。
总结
本教程详细介绍了如何利用PHP的高效数组操作,将两个相关的数组进行重构,以满足特定的数据组织和排序需求。通过构建中间的ID索引映射,我们不仅实现了预期的输出格式,还显著提升了处理大型数据集时的性能。掌握这种数据重构技巧,对于编写高效、可维护的PHP代码至关重要。
以上就是PHP数组重构:根据关联数组值重排对象列表并设置新键的详细内容,更多请关注php中文网其它相关文章!


