Creé un árbol de categorías donde cada categoría contiene subcategorías y cada categoría contiene su contenido asociado. Algunas de las categorías de este árbol contienen subcategorías pero no tienen contenido asociado. ¿Cómo puedo limpiar el árbol de categorías para que la estructura del árbol contenga solo categorías que tengan contenido asociado o que tengan subcategorías que tengan contenido asociado? Es decir, en el árbol de categorías solo deben existir caminos que conduzcan a una categoría que tenga contenido asociado.
La estructura que tengo es una matriz:
[uid_of_category] => (array)content => empty => (array)sub_categories => [uid_of_category] => (array)content => empty => (array)sub_categories => [uid_of_category] => (array)content => [...associated content...] => (array)sub_categories [uid_of_category] => (array)content => empty => (array)sub_categories => [uid_of_category] => (array)content => [...associated content...] => (array)sub_categories => [uid_of_category] => (array)content => empty => (array)sub_categories => [uid_of_category] => (array)content => [...associated content...] => (array)sub_categories ...Traté de usar una función recursiva para llegar a los elementos más bajos del árbol, pero no sé cómo implementar que incluso esos elementos permanezcan en el árbol que no tienen contenido asociado, pero cuyo subelemento tiene contenido asociado.
Obviamente, la recursividad ayudará. Pero usemos dos funciones en lugar de una. Usaremos una función para determinar si una categoría cumple con las condiciones para ser limpiada (eliminada). Otra función para hacer la limpieza. En esta función, el parámetro se pasará por referencia (&$categorías). Todo esto asumiendo que la estructura es una matriz.
cleanCategories($categories); function cleanCategories(&$categories) { foreach ($categories as $key=>&$category) { if (isCleanable($category)) { unset($categories[$key]); } else { cleanCategories($category['sub_categories']); } } } function isCleanable($category) { if (!empty($category['content'])) { return false; } foreach ($category['sub_categories'] as $category) { if (!isCleanable($category)) { return false; } } return true; }Desde este enfoque, puede hacer una solución mejor y más eficiente.
Y no olvides que Stack Overflow no es un servicio de escritura de código. Debes pensar por ti mismo, pensar de nuevo, encontrar una manera (solo pensar), ponerlo en código, probar el código, depurar el código...
Intenté construir una matriz basada en la publicación del OP:
$arr = [ "uid_of_category_0" => [ "content" => [], "sub_categories" => [ "uid_of_category_0_0" => [ "content" => [], "sub_categories" => [] ], "uid_of_category_0_1" => [ "content" => [ "associated_content_0_1_0", "associated_content_0_1_1", "associated_content_0_1_2" ], "sub_categories" => [] ] ] ], "uid_of_category_1" => [ "content" => [], "sub_categories" => [ "uid_of_category_1_0" => [ "content" => [ "associated_content_1_0_0", "associated_content_1_0_1", "associated_content_1_0_2" ], "sub_categories" => [] ], "uid_of_category_1_1" => [ "content" => [], "sub_categories" => [ "uid_of_category_1_1_0" => [ "content" => [ "associated_content_1_1_0_0", "associated_content_1_1_0_1", "associated_content_1_1_0_2" ], "sub_categories" => [] ] ] ] ] ], ];Este sería el código para desarmar todas las matrices vacías dentro de $arr:
function unset_empty_arrays(array $arr): array { foreach (array_keys($arr) as $key) { if (is_array($arr[$key])) { $arr[$key] = unset_empty_arrays($arr[$key]); } if ($arr[$key] === [] && $key === 'sub_categories') { unset($arr[$key]); } } return $arr; } print_r(unset_empty_arrays($arr));Editar: agregado && $key === 'sub_categories'
Este caso se resuelve mejor con un recorrido del árbol posterior al orden.
En el recorrido posterior al orden, primero desea hacer recursividad sobre todos los subárboles. Luego realice la operación requerida en el nodo actual.
function cleanUp(&$categories) { if (empty($categories)) { //no categories, nothing to do here return; } foreach ($categories as $key => &$category) { //first clean up sub categories cleanUp($category['sub_categories']); if (empty($category['sub_categories']) && empty($category['content'])) { //If there are no sub_categories left and there is no content remove category unset($categories[$key]); } } }Después de limpiar las subcategorías, sabe que si quedan subcategorías, deben tener contenido o subcategorías con contenido. Entonces, en ese momento, puede decidir fácilmente si es necesario eliminar la categoría actual.