3

I need to separate a single array into sub arrays based on the amount of times > appears within the array key so that I tell who is a parent category and who isn't. Note that there is no limit to the amount of possible nested parents.

Also, if a child with the same name exists, it is considered unique if it has a different parent.

My source array structure looks like this:

array (
  'Test Parent 2>Test Child>Test Sub Child' => 
  array (
    'content_id_4' => NULL,
  ),
  'Test Parent 3' => 
  array (
    'content_id_4' => NULL,
    'content_id_5' => NULL,
  ),
  'Test Parent>Test Child>Test Sub Child' => 
  array (
    'content_id_3' => NULL,
  ),
  'Test Parent 2 with No Kids' => 
  array (
    'content_id_3' => NULL,
  ),
  'Collections>Sports' => 
  array (
    'content_id_2' => NULL,
    'content_id_22' => NULL,
  ),
  'Collections' => 
  array (
    'content_id_2' => NULL,
    'content_id_22' => NULL,
    'content_id_6' => NULL,
  ),
  'Collections>Charity' => 
  array (
    'content_id_6' => NULL,
  ),
)

In the above example, Test Parent>Test Child>Test Sub Child would mean that there is a parent category Test Parent that has a child Test Child. Test Child also is a parent and has a child called Test Sub Child that does not have any children.

Example output required:

array (
  'Collections' => 
  array (
    'Sports' => NULL,
    'Charity' => NULL,
  ),
  'Test Parent' => 
  array (
    'Test Child' => 
    array (
      'Test Sub Child' => NULL,
    ),
  ),
  'Test Parent 2 with No kids' => NULL,
  'Study' => 
  array (
    'Study Groups' => NULL,
  ),
)

I attempted a solution but can't manage to get the syntax right so that I can create an additional array with a child's children.

I don't necessarily require my example to be refactored. I am simply looking for the best solution that works.

My example code

$category_structure = array();
foreach($event_categories as $main_cat => $content_ids) {

    $this_category_list = explode('>', $main_cat);

    $this_cat = array();
    $this_parent = array_shift($this_category_list);


    foreach($this_category_list as $cat) {
        $this_cat[$this_parent][$cat] = null;
    }

    $category_structure = array_merge_recursive($this_cat, $category_structure);


}
4
  • 1
    Instead of posting a var_dump() of your array, consider posting a var_export() of it instead. Commented Jul 22, 2015 at 12:41
  • @nickb - noted and fixed Commented Jul 22, 2015 at 13:09
  • can you show the code, where this array is coming from? there must be something that can make this easy. @DaveO'Dwyer Commented Jul 22, 2015 at 13:30
  • @Viral The source array is coming from a CMS - I have no control over its data structure. Commented Jul 22, 2015 at 19:46

2 Answers 2

2

This should work for you, making sure there are no zero indexed items in the result. Which comes from array_merge_recursive i think, by merging the null valued item to the ones that have an associative key.

It is not as elegant as P0rnflake's solution though, but i am sure you will get the idea.

$collect = array();
$result = array();
$last = "";
foreach($event_categories as $main_cat => $content_ids) {
    if (strpos($last, $main_cat) === false) {
        array_push($collect, explode('>', $main_cat));
    }
    $last = $main_cat;
} 
array_walk($collect, function($value) use (&$result) {
    $out = array();
    $cur = &$out;
    foreach ($value as $array) {
        if (count($value) !== 1) {
            $cur[$array] = array();
        } else {
            $cur[$array] = null;    
        }
        $cur = &$cur[$array];
    }
    $cur = null;
    $result = array_merge_recursive($result, $out);
});
var_dump($result);
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you Dave. Very much appreciated. This is working exactly as expected.
Sure, happy coding! ;-)
1

This solution should work on php >= 5.3.0 ($yourArray is the input array):

// anonymous recursive function which merges a flat numeric array 
// into a hierarchy, f.e. array('parent','child','grandchild')
// will be built to a hierarchical array
$treeBuilder = function($numArray) use (&$treeBuilder) {
    if(isset($numArray[1])) {
        //recursive merge needed, there are still entries left
        return array(
            $numArray[0] => $treeBuilder(array_slice($numArray, 1))
        );
    }
    //end is reached
    return array(
        $numArray[0] => null
    );
};

$result = array();
foreach (array_keys($yourArray) as $key) {
    // loop through exploded keys and merge results
    $hierarchy = explode('>', $key);
    $result = array_merge_recursive($result, $treeBuilder($hierarchy));
}
var_dump($result);

2 Comments

Thank you for your attempt at this. Resulting array structure looks to fit perfectly apart from a key 0 with a value of null existing in all returned arrays. It appears to be coming from code return array( $numArray[0] => null
ye, you are right, I think this happens from the 'Collections' entry without separator

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.