PHP类别反向遍历算法
我正在尝试优化一个电子商务分类系统,该系统具有无限的分类深度(系统内存限制除外)。我一次检索所有类别,并将其排序为多维数组,大致如下所示:PHP类别反向遍历算法,php,arrays,algorithm,multidimensional-array,traversal,Php,Arrays,Algorithm,Multidimensional Array,Traversal,我正在尝试优化一个电子商务分类系统,该系统具有无限的分类深度(系统内存限制除外)。我一次检索所有类别,并将其排序为多维数组,大致如下所示: [array] ( [0] ( 'CategoryId' => 1, 'ParentCategoryId' => 0, 'Title' => 'Category A', 'SubCategories' => [array] ( [0] ( 'CategoryId' =&g
[array] (
[0] (
'CategoryId' => 1,
'ParentCategoryId' => 0,
'Title' => 'Category A',
'SubCategories' => [array] (
[0] (
'CategoryId' => 2,
'ParentCategoryId' => 1,
'Title' => 'Category B',
'SubCategories' => [array] (
[0] (
'CategoryId' => 3,
'ParentCategoryId' => 2,
'Title' => 'Category C'
)
)
)
)
)
)
数组中的每一项实际上都是一个对象,但为了简单起见,我把它写成了一种数组格式
我可以使用此功能向下遍历我的树:
/**
* Find Branch using Recursive search by Object Key
* @param String Needle
* @param Array Haystack
* @return Array
*/
public static function findBranchByKey($key, $needle, $haystack)
{
foreach ($haystack as $item)
{
if ( $item->$key == $needle || ( is_object($item) && $item = self::findBranchByKey($key, $needle, $item->SubCategories)) )
{
return $item;
}
}
return false;
}
这将查找具有匹配键的对象并返回它(可能包含更多子类别)
我的问题是如何穿越另一个方向。例如,使用上面的数据,假设我正在显示“Category C”,并希望创建其父母的面包屑。我想不出一个好方法来获取我的树数组,跳转到一个特定的子类别,然后向上迭代以获得每个父类。这样的结果数组可能是这样的,因此很容易将它们吐出作为面包屑:
array( 'Category A', 'Category B', 'Category C' )
我可能可以在数据库中使用SQL来实现这一点,但我希望检索一次树,缓存它,并在需要时对该对象执行遍历,而不是进行大量查询
TL;博士如何在多维类别数组中向上遍历?可以通过递归完成 比方说,这个函数应该可以工作:
function getPath($id, $tree, &$path = array()) {
foreach ($tree as $item) {
if ($item['CategoryId'] == $id) {
array_push($path, $item['CategoryId']);
return $path;
}
if (!empty($item['SubCategories'])) {
array_push($path, $item['CategoryId']);
if (getPath($id, $item['SubCategories'], $path) === false) {
array_pop($path);
} else {
return $path;
}
}
}
return false;
}
这:
将导致:
Array ( [0] => 1 [1] => 4 [2] => 5 )
它可以通过递归实现 比方说,这个函数应该可以工作:
function getPath($id, $tree, &$path = array()) {
foreach ($tree as $item) {
if ($item['CategoryId'] == $id) {
array_push($path, $item['CategoryId']);
return $path;
}
if (!empty($item['SubCategories'])) {
array_push($path, $item['CategoryId']);
if (getPath($id, $item['SubCategories'], $path) === false) {
array_pop($path);
} else {
return $path;
}
}
}
return false;
}
这:
将导致:
Array ( [0] => 1 [1] => 4 [2] => 5 )
节点树中的节点(这就是您在这里看到的)应该有一个对其父节点的引用,以及对其所有子节点的引用。您的每个类别似乎都有一个
ParentCategoryId
,我想您应该使用它:除了ParentCategoryId
值之外,还有其他值吗?@cillosParentCategoryId
是一个整数,而不是一个引用。您可以有第二个数组,它是categoryId=>node
的平面数组。这将允许您基于categoryId
或parentCategoryId
查找节点引用,而不必隐藏引用(例如,如果您尝试使用print\r
打印它,这将导致递归问题)。您可以在对元素排序时构建查找表。您可以同样轻松地设置对父节点的引用,但正如我所说的,这将使您在使用某些PHP函数时遇到麻烦,例如print\r
。节点树中的节点(这就是您在这里看到的)应该有对其父节点的引用,以及对其所有子类别的引用。您的每个类别似乎都有一个父类别ID
,我想您会使用它:除了ParentCategoryId
值之外,还有其他值吗?@cillosParentCategoryId
是一个整数,而不是一个引用。您可以有第二个数组,它是categoryId=>node
的平面数组。这将允许您基于categoryId
或parentCategoryId
查找节点引用,而不必隐藏引用(例如,如果您尝试使用print\r
打印它,这将导致递归问题)。您可以在对元素排序时构建查找表。您可以同样轻松地设置对父节点的引用,但正如我所说的,这将使您在使用某些PHP函数时遇到麻烦,例如print\r
+1绝对出色!出于某种原因,我无法找到一个好的方法来进行递归。我真的需要把这类东西打包成一个很好的可重用类并共享它。再次感谢!很高兴听到,@cillosis:)+1绝对精彩!出于某种原因,我无法找到一个好的方法来进行递归。我真的需要把这类东西打包成一个很好的可重用类并共享它。再次感谢!很高兴听到,@cillosis:)